Cómo usar el comando docker compose exec para interactuar con servicios

DockerDockerBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

Introducción

En este laboratorio, aprenderás a utilizar eficazmente el comando docker compose exec para interactuar con servicios en ejecución. Explorarás la ejecución de comandos dentro de un contenedor de servicio, la ejecución de comandos en modo desacoplado (detached mode), la ejecución de comandos como un usuario diferente y la ejecución de comandos con un directorio de trabajo específico. Esta experiencia práctica te proporcionará habilidades esenciales para depurar y gestionar tus aplicaciones en Docker (Dockerized applications).


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker/ContainerOperationsGroup -.-> docker/run("Run a Container") docker/ContainerOperationsGroup -.-> docker/exec("Execute Command in Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") subgraph Lab Skills docker/run -.-> lab-555079{{"Cómo usar el comando docker compose exec para interactuar con servicios"}} docker/exec -.-> lab-555079{{"Cómo usar el comando docker compose exec para interactuar con servicios"}} docker/pull -.-> lab-555079{{"Cómo usar el comando docker compose exec para interactuar con servicios"}} end

Ejecutar un comando en un contenedor de servicio en ejecución

En este paso, aprenderás cómo ejecutar un comando dentro de un contenedor Docker en ejecución. Esta es una técnica muy útil para depurar o interactuar con un servicio que se ejecuta dentro de un contenedor sin necesidad de detenerlo y reiniciarlo.

Primero, descarguemos una imagen simple de Nginx para esta demostración. Usaremos la imagen nginx:alpine ya que es pequeña y rápida de descargar.

docker pull nginx:alpine

Deberías ver una salida que indica que la imagen se está descargando y extrayendo.

A continuación, ejecutaremos esta imagen de Nginx en modo desacoplado (detached mode), lo que significa que el contenedor se ejecutará en segundo plano sin ocupar tu terminal. También le asignaremos un nombre para facilitar su referencia posterior.

docker run -d --name my-nginx nginx:alpine

La salida será el ID del contenedor recién creado y en ejecución.

Ahora que el contenedor está en ejecución, podemos ejecutar un comando dentro de él usando el comando docker exec. La sintaxis básica es docker exec [options] container command [args...]. Intentemos listar los archivos en el directorio raíz del contenedor.

docker exec my-nginx ls /

Deberías ver una lista de directorios y archivos presentes en el sistema de archivos raíz del contenedor Nginx, como bin, etc, usr, etc. Esto confirma que has ejecutado exitosamente un comando dentro del contenedor en ejecución.

Probemos otro comando. Podemos verificar la versión de Nginx que se ejecuta dentro del contenedor.

docker exec my-nginx nginx -v

La salida mostrará la versión de Nginx instalada en el contenedor, por ejemplo, nginx version: nginx/1.24.0.

Esto demuestra cómo puedes interactuar con un contenedor en ejecución y ejecutar comandos arbitrarios dentro de su entorno.

Ejecutar un comando en modo desacoplado

En el paso anterior, ejecutamos un contenedor en modo desacoplado usando el flag -d. Esta es una práctica común cuando deseas que un contenedor se ejecute en segundo plano sin ocupar tu terminal. En este paso, exploraremos más a fondo la ejecución de comandos en modo desacoplado, específicamente usando docker exec.

Aunque docker exec se usa típicamente para sesiones interactivas o para ejecutar comandos cortos en un contenedor en ejecución, también puedes ejecutar un comando en modo desacoplado usando el flag -d con docker exec. Esto es útil para iniciar un proceso en segundo plano dentro de un contenedor que ya está en ejecución.

Usemos el contenedor my-nginx que iniciamos en el paso anterior. Ejecutaremos un comando simple en modo desacoplado. Por ejemplo, ejecutemos un comando que escriba la fecha y hora actuales en un archivo dentro del contenedor cada 5 segundos.

docker exec -d my-nginx sh -c 'while true; do date >> /usr/share/nginx/html/date.txt; sleep 5; done'

En este comando:

  • docker exec -d my-nginx: Ejecuta el siguiente comando en modo desacoplado dentro del contenedor my-nginx.
  • sh -c '...': Ejecuta la cadena de comandos subsiguiente usando el shell sh.
  • while true; do date >> /usr/share/nginx/html/date.txt; sleep 5; done: Este es el comando que se está ejecutando. Es un bucle simple que continuamente añade la fecha y hora actuales al archivo /usr/share/nginx/html/date.txt y luego espera 5 segundos antes de repetirse.

Después de ejecutar el comando, verás el ID del contenedor impreso en tu terminal, lo que indica que el comando se ha iniciado en segundo plano dentro del contenedor.

Para verificar que el comando se está ejecutando y escribiendo en el archivo, podemos ejecutar otro comando para ver el contenido del archivo date.txt. Dado que el comando se ejecuta en segundo plano, puede tardar unos segundos en crearse y llenarse el archivo.

docker exec my-nginx cat /usr/share/nginx/html/date.txt

Deberías ver la fecha y hora impresas en la salida, y si ejecutas el comando cat nuevamente después de unos segundos, deberías ver nuevas entradas añadidas al archivo. Esto confirma que el proceso en segundo plano iniciado con docker exec -d se está ejecutando como se esperaba.

Ejecutar un comando como un usuario diferente

En este paso, aprenderás cómo ejecutar un comando dentro de un contenedor en ejecución como un usuario específico. Por defecto, docker exec ejecuta comandos como el usuario root dentro del contenedor, pero puedes especificar un usuario diferente usando el flag -u o --user. Esto es importante para la seguridad y para cumplir con el principio de mínimo privilegio.

Continuemos usando el contenedor my-nginx. Primero, veamos como qué usuario se ejecuta el comando ls / por defecto.

docker exec my-nginx whoami

La salida probablemente será root, ya que este es el usuario predeterminado para docker exec.

Ahora, intentemos ejecutar un comando como un usuario diferente. La imagen de Nginx típicamente ejecuta el proceso Nginx como un usuario no root, generalmente llamado nginx. Intentemos ejecutar el comando whoami como el usuario nginx.

docker exec -u nginx my-nginx whoami

Deberías ver la salida nginx, confirmando que el comando se ejecutó como el usuario nginx.

También puedes especificar un ID de usuario (UID) en lugar de un nombre de usuario. Para encontrar el UID del usuario nginx dentro del contenedor, podemos consultar el archivo /etc/passwd.

docker exec my-nginx cat /etc/passwd | grep nginx

La salida mostrará la entrada para el usuario nginx, incluyendo su UID y GID (ID de grupo). Por ejemplo, podría verse algo como nginx:x:101:101:nginx user,,,:/nonexistent:/bin/false. En este ejemplo, el UID es 101.

Ahora, ejecutemos el comando whoami usando el UID. Reemplaza 101 con el UID real que encontraste en el paso anterior si es diferente.

docker exec -u 101 my-nginx whoami

La salida debería ser nuevamente nginx, demostrando que puedes usar tanto el nombre de usuario como el UID para especificar el usuario en docker exec.

Ejecutar comandos como un usuario no root es una buena práctica de seguridad, especialmente cuando interactúas con archivos sensibles o realizas operaciones que no requieren privilegios de root.

Ejecutar un comando con un directorio de trabajo específico

En este último paso, aprenderás cómo ejecutar un comando dentro de un contenedor en ejecución con un directorio de trabajo específico. Por defecto, docker exec ejecuta comandos en el directorio de trabajo definido en el Dockerfile de la imagen del contenedor (generalmente /). Sin embargo, puedes cambiar esto usando el flag -w o --workdir. Esto es útil cuando necesitas ejecutar comandos relativos a una ruta específica dentro del sistema de archivos del contenedor.

Continuemos usando el contenedor my-nginx. Primero, veamos el directorio de trabajo predeterminado cuando ejecutamos un comando sin especificar uno. Podemos usar el comando pwd (print working directory) para esto.

docker exec my-nginx pwd

La salida probablemente será /, que es el directorio raíz.

Ahora, ejecutemos un comando en un directorio de trabajo diferente. El contenedor Nginx tiene un directorio /usr/share/nginx/html desde donde el servidor web sirve los archivos. Cambiemos el directorio de trabajo a esta ruta y luego listemos los archivos dentro de él.

docker exec -w /usr/share/nginx/html my-nginx ls

En este comando:

  • docker exec -w /usr/share/nginx/html my-nginx: Ejecuta el siguiente comando dentro del contenedor my-nginx, estableciendo el directorio de trabajo en /usr/share/nginx/html.
  • ls: El comando a ejecutar, que lista los archivos en el directorio de trabajo actual.

Deberías ver los archivos presentes en el directorio /usr/share/nginx/html, como index.html y date.txt (que creamos en un paso anterior).

Probemos otro ejemplo. Podemos crear un nuevo directorio dentro de /usr/share/nginx/html y luego cambiar nuestro directorio de trabajo al directorio recién creado antes de ejecutar un comando.

docker exec my-nginx mkdir /usr/share/nginx/html/new_dir
docker exec -w /usr/share/nginx/html/new_dir my-nginx pwd

El primer comando crea un directorio llamado new_dir dentro de /usr/share/nginx/html. El segundo comando luego cambia el directorio de trabajo a /usr/share/nginx/html/new_dir e imprime el directorio de trabajo actual.

La salida del segundo comando debería ser /usr/share/nginx/html/new_dir, confirmando que el directorio de trabajo fue cambiado exitosamente para la ejecución del comando pwd.

Usar el flag -w con docker exec te permite ejecutar comandos en el contexto de un directorio específico dentro del contenedor, lo cual es muy útil para navegar e interactuar con el sistema de archivos del contenedor de manera más eficiente.

Resumen

En este laboratorio, aprendiste a utilizar el comando docker exec para interactuar con un contenedor Docker en ejecución. Practicaste la ejecución de comandos dentro de un contenedor, específicamente listando archivos y verificando la versión de Nginx, demostrando la capacidad de depurar e interactuar con servicios sin necesidad de detenerlos.

También exploraste brevemente la ejecución de contenedores en modo desatendido (detached) usando el flag -d, un concepto fundamental para la ejecución de contenedores en segundo plano. Aunque los pasos posteriores no se detallaron completamente, los pasos iniciales proporcionaron una base sólida para comprender cómo ejecutar comandos dentro de un entorno de contenedor en ejecución.