Ejecutar un comando sin iniciar servicios vinculados
En este paso, aprenderemos cómo ejecutar un comando en un contenedor Docker que forma parte de una aplicación multi-contenedor, sin iniciar los demás servicios vinculados. Esto es particularmente útil para ejecutar migraciones de bases de datos, scripts de configuración o comandos de depuración en un servicio sin necesidad de levantar toda la pila de la aplicación.
Aunque Docker Compose es la herramienta estándar para gestionar aplicaciones multi-contenedor y tiene funciones para ejecutar comandos puntuales en servicios específicos, aquí demostraremos los conceptos subyacentes de Docker. Como Docker Compose no está preinstalado en este entorno, nos centraremos en usar el comando docker run
con redes.
Simularemos un escenario simple con dos contenedores: una aplicación web y una base de datos. Usaremos una imagen genérica ubuntu
para representar nuestra aplicación web y una imagen postgres
para la base de datos.
Primero, descarguemos la imagen postgres
:
docker pull postgres:latest
Deberías ver una salida que indica que la imagen se está descargando.
Using default tag: latest
latest: Pulling from library/postgres
...
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest
Ahora, creemos una red Docker para que nuestros contenedores puedan comunicarse entre sí por nombre.
docker network create my-app-network
Deberías ver el ID de la red impreso.
<network_id>
A continuación, ejecutemos el contenedor postgres
y conectémoslo a nuestra red. También estableceremos una contraseña para el usuario de PostgreSQL.
docker run -d --network my-app-network --name my-database -e POSTGRES_PASSWORD=mypassword postgres
Deberías ver el ID del contenedor impreso, indicando que el contenedor de la base de datos se está ejecutando en segundo plano.
<container_id>
Ahora, imaginemos que nuestro contenedor de "aplicación web" necesita ejecutar un comando que interactúe con la base de datos, como un script de migración. Normalmente, si estuviéramos usando Docker Compose, podríamos ejecutar un comando en el servicio web y Docker Compose manejaría la configuración de red y los enlaces.
Usando solo docker run
, si ejecutáramos el contenedor de la aplicación web e intentara conectarse a my-database
, normalmente necesitaría estar en la misma red.
Ejecutemos un comando en un contenedor ubuntu
conectado a la misma red, simulando un comando que podría interactuar con la base de datos. Intentaremos hacer ping al contenedor de la base de datos por su nombre (my-database
).
docker run --network my-app-network ubuntu ping -c 4 my-database
Este comando:
- Creará un nuevo contenedor desde la imagen
ubuntu
.
- Lo conectará a
my-app-network
.
- Ejecutará el comando
ping -c 4 my-database
dentro del contenedor.
Como el contenedor ubuntu
está en la misma red que el contenedor my-database
, puede resolver el nombre my-database
a la dirección IP del contenedor de la base de datos y hacerle ping.
Deberías ver una salida mostrando las solicitudes y respuestas de ping:
PING my-database (172.18.0.2) 56(84) bytes of data.
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.054 ms
--- my-database ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.050/0.053/0.054/0.001 ms
Esto demuestra que puedes ejecutar un comando puntual en un contenedor y hacer que interactúe con otros contenedores en la misma red, sin necesidad de iniciar el servicio predeterminado del contenedor que ejecuta el comando (en este caso, el contenedor ubuntu
no tiene un "servicio" típico). La clave es conectar el contenedor que ejecuta el comando a la misma red que los servicios con los que necesita interactuar.
Finalmente, limpiemos el contenedor de la base de datos en ejecución y la red.
docker stop my-database
my-database
docker rm my-database
my-database
docker network rm my-app-network
my-app-network