Aplicaciones multicontenedor
Hasta este punto, has estado trabajando con aplicaciones de un solo contenedor. Pero ahora agregarás MySQL a la pila de la aplicación. A menudo surge la siguiente pregunta: "¿Dónde se ejecutará MySQL? ¿Se instala en el mismo contenedor o se ejecuta por separado?". En general, cada contenedor debe hacer una sola cosa y hacerla bien. A continuación se presentan algunas razones para ejecutar el contenedor por separado:
- Es muy probable que tengas que escalar las API y las interfaces frontend de manera diferente a las bases de datos.
- Los contenedores separados te permiten gestionar versiones y actualizarlas de forma aislada.
- Si bien puedes usar un contenedor para la base de datos de manera local, es posible que desees utilizar un servicio gestionado para la base de datos en producción. En ese caso, no querrás distribuir tu motor de base de datos junto con tu aplicación.
- Ejecutar múltiples procesos requerirá un gestor de procesos (el contenedor solo inicia un proceso), lo que agrega complejidad al inicio y apagado del contenedor.
Y existen más razones. Por lo tanto, como se muestra en el siguiente diagrama, lo mejor es ejecutar tu aplicación en múltiples contenedores.

Redes de contenedores
Recuerda que los contenedores, por defecto, se ejecutan de forma aislada y no saben nada acerca de otros procesos o contenedores en la misma máquina. Entonces, ¿cómo permites que un contenedor se comunique con otro? La respuesta son las redes. Si colocas los dos contenedores en la misma red, podrán comunicarse entre sí.
Iniciar MySQL
Existen dos formas de colocar un contenedor en una red:
- Asignar la red al iniciar el contenedor.
- Conectar un contenedor que ya está en ejecución a una red.
En los siguientes pasos, primero crearás la red y luego conectarás el contenedor MySQL al iniciar.
Crea la red.
$ docker network create todo-appInicia un contenedor MySQL y conéctalo a la red. También vas a definir algunas variables de entorno que la base de datos utilizará para inicializarse. Para obtener más información sobre las variables de entorno de MySQL, consulta la sección "Environment Variables" en la página de MySQL en Docker Hub.
$ docker run -d \ --network todo-app --network-alias mysql \ -v todo-mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=secret \ -e MYSQL_DATABASE=todos \ mysql:8.0$ docker run -d ` --network todo-app --network-alias mysql ` -v todo-mysql-data:/var/lib/mysql ` -e MYSQL_ROOT_PASSWORD=secret ` -e MYSQL_DATABASE=todos ` mysql:8.0$ docker run -d ^ --network todo-app --network-alias mysql ^ -v todo-mysql-data:/var/lib/mysql ^ -e MYSQL_ROOT_PASSWORD=secret ^ -e MYSQL_DATABASE=todos ^ mysql:8.0En el comando anterior, puedes ver la bandera
--network-alias. En una sección posterior aprenderás más sobre esta bandera.TipNotarás un volumen llamado
todo-mysql-dataen el comando anterior que está montado en/var/lib/mysql, que es donde MySQL almacena sus datos. Sin embargo, nunca ejecutaste un comandodocker volume create. Docker reconoce que deseas usar un volumen con nombre y crea uno automáticamente por ti.Para confirmar que tienes la base de datos en funcionamiento, conéctate a ella y verifica que la conexión se establezca.
$ docker exec -it <mysql-container-id> mysql -u root -pCuando aparezca la solicitud de contraseña, escribe
secret. En la consola de MySQL, enumera las bases de datos y verifica que veas la base de datostodos.mysql> SHOW DATABASES;Deberías ver una salida parecida a esta:
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | todos | +--------------------+ 5 rows in set (0.00 sec)Sal de la consola de MySQL para regresar a la terminal de tu máquina.
mysql> exitAhora tienes una base de datos
todoslista para usar.
Conectar a MySQL
Ahora que sabes que MySQL está en funcionamiento, puedes usarlo. Pero, ¿cómo lo usas? Si ejecutas otro contenedor en la misma red, ¿cómo encuentras ese contenedor? Recuerda que cada contenedor tiene su propia dirección IP.
Para responder a las preguntas anteriores y comprender mejor las redes de contenedores, vas a utilizar el contenedor nicolaka/netshoot, que incluye una gran cantidad de herramientas útiles para solucionar problemas o depurar redes.
Inicia un nuevo contenedor utilizando la imagen
nicolaka/netshoot. Asegúrate de conectarlo a la misma red.$ docker run -it --network todo-app nicolaka/netshootDentro del contenedor, vas a utilizar el comando
dig, que es una herramienta de DNS muy útil. Buscarás la dirección IP para el nombre de hostmysql.$ dig mysqlDeberías obtener una salida como la siguiente.
; <<>> DiG 9.18.8 <<>> mysql ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;mysql. IN A ;; ANSWER SECTION: mysql. 600 IN A 172.23.0.2 ;; Query time: 0 msec ;; SERVER: 127.0.0.11#53(127.0.0.11) ;; WHEN: Tue Oct 01 23:47:24 UTC 2019 ;; MSG SIZE rcvd: 44En la sección "ANSWER SECTION", verás un registro
Aparamysqlque se resuelve en172.23.0.2(es muy probable que tu dirección IP tenga un valor diferente). Aunque normalmentemysqlno es un nombre de host válido, Docker pudo resolverlo a la dirección IP del contenedor que tenía ese alias de red. Recuerda que utilizaste--network-aliasanteriormente.Lo que esto significa es que tu aplicación simplemente necesita conectarse a un host llamado
mysqlpara comunicarse con la base de datos.
Ejecutar tu aplicación con MySQL
La aplicación de tareas admite la configuración de algunas variables de entorno para especificar los parámetros de conexión a MySQL. Estas son:
MYSQL_HOST: el nombre de host del servidor MySQL en ejecución.MYSQL_USER: el nombre de usuario que se utilizará para la conexión.MYSQL_PASSWORD: la contraseña que se utilizará para la conexión.MYSQL_DB: la base de datos que se utilizará una vez conectado.
NoteSi bien el uso de variables de entorno para configurar la conexión es generalmente aceptado en desarrollo, se desaconseja totalmente al ejecutar aplicaciones en producción. Diogo Mónica, exjefe de seguridad de Docker, escribió un artículo de blog fantástico explicando los motivos.
Un mecanismo más seguro es utilizar el soporte de secretos proporcionado por tu framework de orquestación de contenedores. En la mayoría de los casos, estos secretos se montan como archivos en el contenedor en ejecución. Verás que muchas aplicaciones (incluida la imagen de MySQL y la aplicación de tareas) también admiten variables de entorno con el sufijo
_FILEpara apuntar a un archivo que contiene la variable.Por ejemplo, configurar la variable
MYSQL_PASSWORD_FILEhará que la aplicación use el contenido del archivo referenciado como la contraseña de conexión. Docker no hace nada especial para soportar estas variables de entorno de forma nativa. Tu aplicación deberá estar diseñada para buscar la variable y leer el contenido del archivo.
Ahora puedes iniciar tu contenedor preparado para desarrollo.
Especifica cada una de las variables de entorno anteriores, además de conectar el contenedor a la red de tu aplicación. Asegúrate de estar en el directorio
getting-started-appcuando ejecutes este comando.$ docker run -dp 127.0.0.1:3000:3000 \ -w /app -v ".:/app" \ --network todo-app \ -e MYSQL_HOST=mysql \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=secret \ -e MYSQL_DB=todos \ node:24-alpine \ sh -c "npm install && npm run dev"En Windows, ejecuta este comando en PowerShell.
$ docker run -dp 127.0.0.1:3000:3000 ` -w /app -v ".:/app" ` --network todo-app ` -e MYSQL_HOST=mysql ` -e MYSQL_USER=root ` -e MYSQL_PASSWORD=secret ` -e MYSQL_DB=todos ` node:24-alpine ` sh -c "npm install && npm run dev"En Windows, ejecuta este comando en Command Prompt (Símbolo del sistema).
$ docker run -dp 127.0.0.1:3000:3000 ^ -w /app -v "%cd%:/app" ^ --network todo-app ^ -e MYSQL_HOST=mysql ^ -e MYSQL_USER=root ^ -e MYSQL_PASSWORD=secret ^ -e MYSQL_DB=todos ^ node:24-alpine ^ sh -c "npm install && npm run dev"$ docker run -dp 127.0.0.1:3000:3000 \ -w //app -v "/.:/app" \ --network todo-app \ -e MYSQL_HOST=mysql \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=secret \ -e MYSQL_DB=todos \ node:24-alpine \ sh -c "npm install && npm run dev"Si observas los registros del contenedor (
docker logs -f <container-id>), deberías ver un mensaje similar al siguiente, que indica que está utilizando la base de datos MySQL.[nodemon] 3.1.11 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,cjs,json [nodemon] starting `node src/index.js` Waiting for mysql:3306. Connected! Connected to mysql db at host mysql Listening on port 3000Abre la aplicación en tu navegador y agrega algunos elementos a tu lista de tareas.
Conéctate a la base de datos MySQL y demuestra que los elementos se están escribiendo en la base de datos. Recuerda que la contraseña es
secret.$ docker exec -it <mysql-container-id> mysql -p todosY en la consola de MySQL, ejecuta lo siguiente:
mysql> select * from todo_items; +--------------------------------------+--------------------+-----------+ | id | name | completed | +--------------------------------------+--------------------+-----------+ | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! | 0 | | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome! | 0 | +--------------------------------------+--------------------+-----------+Tu tabla se verá diferente porque tendrá tus elementos. Pero deberías verlos almacenados allí.
Resumen
En este punto, tienes una aplicación que ahora almacena sus datos en una base de datos externa que se ejecuta en un contenedor separado. Aprendiste un poco sobre redes de contenedores y descubrimiento de servicios utilizando DNS.
Información relacionada:
Siguientes pasos
Es muy probable que comiences a sentirte un poco abrumado con todo lo que necesitas hacer para iniciar esta aplicación. Tienes que crear una red, iniciar contenedores, especificar todas las variables de entorno, exponer puertos y más. Eso es mucho que recordar y ciertamente dificulta el compartirlo con otra persona.
En la siguiente sección, aprenderás sobre Docker Compose. Con Docker Compose, puedes compartir las pilas de tu aplicación de una manera mucho más sencilla y permitir que otros las pongan en marcha con un comando único y simple.
Usar Docker Compose