Introducción
Los contenedores Docker son las piezas fundamentales del despliegue de aplicaciones modernas. En este laboratorio, exploraremos técnicas avanzadas de gestión de contenedores que profundizarán tu comprensión de las capacidades de Docker. Cubriremos la ejecución de contenedores en diferentes modos, la gestión de su ciclo de vida, la inspección de detalles técnicos, el trabajo con registros (logs), la ejecución de comandos dentro de contenedores activos, la copia de archivos, la configuración de variables de entorno y la restricción de recursos del sistema. Al finalizar esta sesión, tendrás un conocimiento integral sobre cómo trabajar con contenedores Docker de manera eficiente.
Ejecución de Contenedores en Diferentes Modos
Docker permite ejecutar contenedores en distintos modos para adaptarse a diversos casos de uso. Exploraremos los dos más comunes: el modo desatendido (detached) y el modo interactivo.
Primero, ejecutemos un contenedor en modo desatendido:
docker run -d --name nginx-detached nginx
Este comando realiza lo siguiente:
-d: Ejecuta el contenedor en segundo plano (modo detached).--name nginx-detached: Asigna el nombre "nginx-detached" al contenedor.nginx: Especifica la imagen a utilizar (se descargará de Docker Hub si no está disponible localmente).
Deberías ver una cadena larga de caracteres como salida, que representa el ID del contenedor.
Puedes verificar el estado del contenedor ejecutando:
docker ps
Ahora, ejecutemos un contenedor en modo interactivo:
docker run -it --name ubuntu-interactive ubuntu /bin/bash
Este comando realiza lo siguiente:
-it: Ejecuta el contenedor en modo interactivo con un pseudo-TTY.--name ubuntu-interactive: Asigna el nombre "ubuntu-interactive" al contenedor.ubuntu: Especifica la imagen a utilizar./bin/bash: El comando a ejecutar dentro del contenedor (en este caso, una terminal bash).
Ahora deberías estar dentro del contenedor Ubuntu. Puedes salir del mismo escribiendo exit.
Listemos nuestros contenedores activos:
docker ps
Deberías ver el contenedor nginx-detached en ejecución, pero no el ubuntu-interactive (ya que salimos de él).
Gestión del Ciclo de Vida del Contenedor
Comprender cómo iniciar, detener y reiniciar contenedores es fundamental para una administración eficaz.
Comencemos deteniendo el contenedor nginx-detached:
docker stop nginx-detached
Ahora, verifiquemos el estado de nuestros contenedores:
docker ps -a
Verás que el contenedor nginx-detached se encuentra ahora en estado "Exited".
Iniciémoslo de nuevo:
docker start nginx-detached
Comprueba el estado una vez más:
docker ps
El contenedor nginx-detached debería aparecer ahora con el estado "Up".
También podemos reiniciar un contenedor que ya esté en funcionamiento:
docker restart nginx-detached
Para ver el estado actual de todos nuestros contenedores, incluidos los detenidos, usa:
docker ps -a
Deberías ver listados tanto nginx-detached como ubuntu-interactive, con sus respectivos estados actuales.
Eliminemos el contenedor detenido ubuntu-interactive:
docker rm ubuntu-interactive
Y verifiquemos que ha sido eliminado:
docker ps -a
El contenedor ubuntu-interactive ya no debería aparecer en la lista.
Inspección de Detalles del Contenedor
Docker ofrece herramientas potentes para inspeccionar los pormenores de tus contenedores. Vamos a explorarlas.
Para obtener información detallada sobre un contenedor, utiliza el comando inspect:
docker inspect nginx-detached
Este comando devuelve un arreglo JSON con información técnica exhaustiva. Como puede resultar abrumador, utilizaremos filtros para obtener datos específicos.
Para obtener la dirección IP del contenedor:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx-detached
Para ver el estado actual del contenedor:
docker inspect -f '{{.State.Status}}' nginx-detached
Estos comandos utilizan plantillas de Go para filtrar la salida. El indicador -f nos permite especificar el formato deseado.
Comprobemos también el mapeo de puertos:
docker port nginx-detached
El mapeo de puertos permite que los contenedores se comuniquen con el sistema anfitrión o redes externas, vinculando un puerto del host con un puerto interno del contenedor. Esto es vital para acceder a servicios internos desde fuera del entorno Docker.
Si no hay puertos mapeados, este comando no producirá ninguna salida. En nuestro caso, no hemos mapeado puertos explícitamente para nginx-detached, por lo que es probable que no veas nada.
Para demostrar el mapeo de puertos, creemos un nuevo contenedor Nginx con un puerto asignado:
docker run -d --name nginx-with-port -p 8080:80 nginx
Este comando mapea el puerto 8080 del host al puerto 80 del contenedor. Ahora, si verificamos los puertos:
docker port nginx-with-port
Deberías ver una salida similar a:
80/tcp -> 0.0.0.0:8080
Esto significa que el tráfico dirigido al puerto 8080 de tu máquina anfitriona se redirigirá al puerto 80 del contenedor, donde Nginx está escuchando.
Trabajo con Registros del Contenedor
Acceder y comprender los registros (logs) es crucial para la resolución de problemas y el monitoreo de tus aplicaciones.
Veamos los registros de nuestro contenedor nginx:
docker logs nginx-detached
Esto muestra todos los registros desde el inicio del contenedor. Para ver solo los más recientes, puedes usar la opción --tail:
docker logs --tail 10 nginx-detached
Esto mostrará únicamente las últimas 10 líneas.
Para seguir los registros en tiempo real (similar a tail -f), usa la opción -f:
docker logs -f nginx-detached
Esto transmitirá las nuevas entradas de registro a medida que se generen. Presiona Ctrl+C para salir del flujo de datos.
También puedes incluir marcas de tiempo en los registros:
docker logs --timestamps nginx-detached
Esto resulta especialmente útil para depurar problemas donde el factor tiempo es crítico.
Ejecución de Comandos en Contenedores Activos
Docker permite ejecutar comandos dentro de un contenedor que ya está en marcha, lo cual es increíblemente útil para tareas de mantenimiento y depuración.
Comencemos ejecutando un comando simple en nuestro contenedor nginx:
docker exec nginx-detached echo "Hola desde dentro del contenedor"
Deberías ver el mensaje impreso en tu terminal.
Ahora, obtengamos una terminal interactiva dentro del contenedor:
docker exec -it nginx-detached /bin/bash
Ahora estás dentro del contenedor. Exploremos un poco:
ls /etc/nginx
cat /etc/nginx/nginx.conf
exit
Estos comandos listan el contenido del directorio de configuración de Nginx y muestran el archivo de configuración principal. El comando exit te devuelve a la terminal de tu sistema anfitrión.
Copia de Archivos hacia y desde Contenedores
Docker proporciona una forma de copiar archivos entre tu sistema anfitrión y los contenedores. Esto es útil para actualizar configuraciones o extraer registros.
Primero, creemos un archivo HTML sencillo en nuestro sistema anfitrión:
echo "<html><body><h1>Hola desde el host</h1></body></html>" > hello.html
Ahora, copiemos este archivo dentro de nuestro contenedor nginx:
docker cp hello.html nginx-detached:/usr/share/nginx/html/hello.html
Podemos verificar que el archivo se copió correctamente ejecutando un comando en el contenedor:
docker exec nginx-detached cat /usr/share/nginx/html/hello.html
Deberías ver el contenido del archivo HTML.
Ahora, copiemos un archivo desde el contenedor hacia nuestro host:
docker cp nginx-detached:/etc/nginx/nginx.conf ~/project/nginx.conf
Esto copia el archivo de configuración de Nginx desde el contenedor a nuestro directorio actual en el host.
Verifica que el archivo se haya copiado:
ls -l ~/project/nginx.conf
Deberías ver el archivo nginx.conf en el listado.
Configuración de Variables de Entorno en Contenedores
Las variables de entorno son una forma fundamental de configurar aplicaciones que se ejecutan en contenedores. Veamos cómo establecerlas y usarlas.
Primero, ejecutemos un nuevo contenedor con una variable de entorno:
docker run --name env-test -e MY_VAR="Hola, Entorno" -d ubuntu sleep infinity
Este comando hace lo siguiente:
--name env-test: Nombra al contenedor "env-test".-e MY_VAR="Hola, Entorno": Define una variable de entorno llamada MY_VAR.-d: Ejecuta el contenedor en segundo plano.ubuntu: Utiliza la imagen de Ubuntu.sleep infinity: Mantiene el contenedor en ejecución indefinidamente.
Ahora, verifiquemos que la variable se haya configurado:
docker exec env-test env | grep MY_VAR
Deberías ver MY_VAR=Hola, Entorno en la salida.
También podemos definir variables usando un archivo. Crea un archivo llamado env_file con el siguiente contenido.
Puedes usar nano o vim para crearlo:
nano env_file
ANOTHER_VAR=Desde un archivo
YET_ANOTHER_VAR=Tambien desde el archivo
Sal del editor y guarda los cambios presionando Ctrl+X, luego Y y Enter.
Ahora, iniciemos otro contenedor utilizando este archivo:
docker run --name env-file-test --env-file env_file -d ubuntu sleep infinity
Verifica las variables en este nuevo contenedor:
docker exec env-file-test env | grep -E "ANOTHER_VAR|YET_ANOTHER_VAR"
Deberías ver ambas variables del archivo en la salida.
Limitación de Recursos del Contenedor
Docker permite limitar los recursos (CPU y memoria) que un contenedor puede consumir. Esto es vital para gestionar la asignación de recursos en entornos con múltiples contenedores.
Iniciemos un contenedor con límites de memoria y CPU:
docker run --name limited-nginx -d --memory=512m --cpus=0.5 nginx
Este comando realiza lo siguiente:
--name limited-nginx: Nombra al contenedor "limited-nginx".-d: Lo ejecuta en segundo plano.--memory=512m: Limita el contenedor a 512 megabytes de memoria RAM.--cpus=0.5: Limita el contenedor a usar, como máximo, la mitad de un núcleo de CPU.nginx: Utiliza la imagen de Nginx.
Podemos verificar estos límites con el comando inspect:
docker inspect -f '{{.HostConfig.Memory}}' limited-nginx
docker inspect -f '{{.HostConfig.NanoCpus}}' limited-nginx
El primer comando devolverá 536870912 (512MB en bytes) y el segundo devolverá 500000000 (0.5 CPU en unidades nano).
Para ver cómo afectan estos límites al contenedor en tiempo real, podemos usar el comando stats:
docker stats limited-nginx
Esto mostrará un flujo en vivo de las estadísticas de uso de recursos. Presiona Ctrl+C para salir de esta vista.
Resumen
En este laboratorio, hemos explorado técnicas avanzadas de gestión de contenedores en Docker. Aprendimos a ejecutar contenedores en diferentes modos, gestionar su ciclo de vida, inspeccionar detalles técnicos, trabajar con registros, ejecutar comandos internos, copiar archivos, configurar variables de entorno y limitar el uso de recursos del sistema. Estas habilidades constituyen una base sólida para trabajar con Docker en escenarios más complejos.
Recuerda que una gestión eficaz de los contenedores es fundamental para construir aplicaciones contenedorizadas escalables y fáciles de mantener. A medida que continúes tu camino con Docker, estas habilidades te resultarán invaluables para depurar, optimizar y administrar tus entornos.
Sigue practicando estos comandos y explorando las capacidades de Docker. Cuanto más trabajes con contenedores, más natural y fluido te resultará su manejo. ¡Feliz aprendizaje!



