- Introducción
- Capítulo 1 Primeros pasos con Docker: Comandos esenciales.
- Capítulo 2 Creación de tu primera imagen de Docker con un Dockerfile.
- Capítulo 3 Gestión de aplicaciones multi-contenedor con Docker Compose.
- Capítulo 4 Escritura de un script para automatizar actualizaciones de contenedores.
- Capítulo 5 Simplificación de tareas comunes con scripts auxiliares.
- Capítulo 6 Técnicas avanzadas de Dockerfile para construcciones optimizadas.
- Capítulo 7 Automatización de construcciones y envíos con GitHub Actions.
- Capítulo 8 Scripting para entornos de desarrollo.
- Capítulo 9 Scripts para integración continua y pruebas.
- Capítulo 10 Creación de scripts de punto de entrada personalizados para contenedores flexibles.
- Capítulo 11 Gestión de contextos de Docker en scripts de Bash.
- Capítulo 12 Scripting para la creación y gestión de redes.
- Capítulo 13 Automatización de la gestión de volúmenes y persistencia de datos.
- Capítulo 14 Un script para limpiar recursos de Docker no utilizados.
- Capítulo 15 Scripting para la copia de seguridad y restauración de volúmenes de Docker.
- Capítulo 16 Automatización de la poda de imágenes de Docker.
- Capítulo 17 Scripting de comprobaciones de salud para tus contenedores.
- Capítulo 18 Construcción de un script en Python para interactuar con la API de Docker.
- Capítulo 19 Creación de un script de gestión de usuarios para entornos de Docker compartidos.
- Capítulo 20 Scripting para el despliegue de una aplicación full stack.
- Capítulo 21 Un script para inspeccionar y formatear información de contenedores.
- Capítulo 22 Automatización del etiquetado y envío de imágenes a un registro.
- Capítulo 23 Scripting para el manejo seguro de secretos en Docker.
- Capítulo 24 Un script para detener y eliminar contenedores de forma elegante.
- Capítulo 25 Scripting avanzado: Combinación de comandos de Docker para flujos de trabajo complejos.
Docker: scripts útiles
Índice
Introducción
Existe un momento distinto en el recorrido de todo usuario de Docker que se siente como una revelación menor. A menudo llega después de escribir docker run con una docena de banderas por vigésima vez en una hora, o después de ejecutar minuciosamente una secuencia de comandos docker ps, docker stop y docker rm para limpiar un entorno local. Es el momento en que te recuestas en tu silla, miras la línea de comandos y piensas: "Tiene que haber una forma más eficiente de hacer esto". Por supuesto, estás absolutamente en lo correcto. El camino desde los comandos manuales repetitivos hasta la eficiencia optimizada está pavimentado con scripts.
Docker ha cambiado fundamentalmente la forma en que construimos, enviamos y ejecutamos software. Ofrece una promesa increíble: un entorno consistente, aislado y portátil para cualquier aplicación. Al empaquetar una aplicación y sus dependencias en una sola unidad estandarizada llamada contenedor, Docker resuelve el clásico problema de "en mi máquina funciona" que ha plagado a los desarrolladores durante décadas. Este enfoque de contenerización proporciona una alternativa ligera a las máquinas virtuales tradicionales al virtualizar el sistema operativo en lugar del hardware subyacente. Esta eficiencia significa que puedes ejecutar múltiples contenedores en un solo host, cada uno con su propio conjunto aislado de procesos y recursos.
El poder de Docker reside en su simplicidad y en su robusta interfaz de línea de comandos (CLI). Con unos pocos comandos, puedes descargar una imagen de un registro como Docker Hub, ejecutarla como contenedor y tener una aplicación compleja, como una base de datos o un servidor web, funcionando en segundos. Esto es un salto monumental respecto a los días de las instalaciones manuales y la compleja gestión de dependencias. Sin embargo, depender únicamente de comandos escritos manualmente es como tener un coche deportivo y conducirlo solo en primera marcha. Estás experimentando la función principal, pero te pierdes la velocidad, la potencia y la elegancia de las que es verdaderamente capaz.
Aquí es donde entra en escena la escritura de scripts. Un script es, en esencia, un conjunto de instrucciones guardado en un archivo, diseñado para ser ejecutado por un programa. Para los usuarios de Docker, esto suele significar scripts de shell (como Bash) o scripts escritos en un lenguaje de alto nivel como Python. Estos scripts toman los comandos individuales y atómicos de la CLI de Docker y los entrelazan en flujos de trabajo potentes y automatizados. Transforman procesos manuales de múltiples pasos y propensos a errores en un único comando fiable. Son la clave para desbloquear todo el potencial de tu entorno Docker.
Piensa en las tareas rutinarias que realizas a diario. Iniciar un entorno de desarrollo específico con múltiples contenedores enlazados. Hacer una copia de seguridad de un volumen crítico de base de datos. Limpiar imágenes y contenedores sin usar para recuperar espacio en disco. Actualizar una aplicación en ejecución a una nueva versión de imagen sin tiempo de inactividad. Cada uno de estos flujos de trabajo implica una secuencia de comandos Docker, y cada uno es un candidato perfecto para la automatización mediante scripts. Un script bien escrito garantiza que estas tareas se realicen de forma consistente cada vez, eliminando el riesgo de error humano, como olvidar una bandera de línea de comandos o escribir incorrectamente un nombre de contenedor.
Este libro nace de la necesidad práctica de esa automatización. Aunque hay innumerables recursos disponibles para enseñarte los fundamentos de Docker —qué es una imagen, cómo escribir un Dockerfile, el propósito de un contenedor—, muchos se detienen ahí. Te dan los bloques de construcción, pero no siempre te muestran cómo ensamblarlos en algo mayor. Este libro es diferente. No es solo otra guía de comandos Docker; es un compendio práctico y directo de scripts útiles diseñados para resolver problemas del mundo real y hacer tu vida como desarrollador, administrador de sistemas o ingeniero de DevOps significativamente más fácil.
Avanzaremos más allá de los comandos básicos docker run y docker build para explorar el arte de la escritura de scripts. Este libro es una colección de recetas, un kit de herramientas de soluciones listas para usar para los desafíos comunes, y a veces no tan comunes, a los que te enfrentas al trabajar con Docker. Cada capítulo está dedicado a una tarea específica y proporciona un script completo y funcional que puedes usar inmediatamente. Lo que es más importante, desglosaremos cómo funciona cada script, explicando los comandos, la lógica y las técnicas utilizadas, para que no solo puedas usar los scripts, sino también comprenderlos, adaptarlos y extenderlos para ajustarlos a tus requisitos únicos.
Entonces, ¿para quién es este libro? Es para el desarrollador que quiere crear una configuración consistente de su entorno de desarrollo local con un solo comando. Es para el administrador de sistemas que necesita gestionar hosts Docker y automatizar tareas de mantenimiento rutinario como copias de seguridad y limpieza. Es para el profesional de DevOps que está construyendo pipelines robustos de integración continua y despliegue continuo (CI/CD). En esencia, este libro es para cualquiera que haya experimentado ese momento de "tiene que haber una forma mejor" y esté listo para abrazar la automatización.
El único requisito previo es una comprensión fundamental de Docker. Debes estar familiarizado con conceptos básicos como imágenes, contenedores, volúmenes y redes. Debes tener Docker instalado y algo de experiencia ejecutando comandos básicos. Sin embargo, no necesitas ser un gurú de los scripts. Empezaremos con scripts de shell simples e iremos introduciendo gradualmente técnicas más avanzadas e incluso profundizaremos en el uso de la API de Docker con Python, asegurando que el material sea accesible independientemente de tu nivel actual de habilidad en scripting.
A lo largo de los capítulos de este libro, nos embarcaremos en un viaje de lo simple a lo complejo. Comenzamos asegurando una base sólida, cubriendo comandos esenciales y los fundamentos de la construcción de imágenes con un Dockerfile y la gestión de configuraciones multi-contenedor con Docker Compose. Estos primeros capítulos sientan las bases, asegurando que tengas los bloques de construcción necesarios a tu disposición antes de empezar a ensamblarlos en flujos de trabajo automatizados. Sirven como repaso y línea base para el trabajo de scripting que vendrá.
A partir de ahí, nos sumergimos de lleno en el mundo de la automatización. Aprenderás a escribir un script que pueda descargar automáticamente una nueva versión de una imagen y reiniciar un contenedor para completar una actualización, una piedra angular del mantenimiento de aplicaciones en ejecución. Exploraremos la creación de scripts auxiliares genéricos que pueden simplificar una amplia gama de tareas comunes, haciendo que tus interacciones con Docker en la línea de comandos sean más potentes y menos verbosas. Estos scripts están diseñados para ser herramientas prácticas que puedas integrar en tu flujo de trabajo inmediatamente.
Una parte significativa de nuestro viaje se dedicará al fino arte de la gestión de recursos. Los entornos Docker, especialmente los usados intensivamente para desarrollo y pruebas, pueden llenarse rápidamente de imágenes, volúmenes y contenedores detenidos sin usar, consumiendo valioso espacio en disco. Proporcionaremos y diseccionaremos scripts específicamente diseñados para limpiar este desorden de forma segura y eficiente. Aprenderás a automatizar la poda de imágenes antiguas y cómo implementar un script que elimine inteligentemente solo los recursos que ya no se necesitan.
Los datos son el alma de muchas aplicaciones, y gestionarlos dentro de un mundo contenerizado presenta sus propios desafíos. Los abordaremos directamente con capítulos sobre scripting para la gestión de volúmenes Docker. Aprenderás a escribir scripts robustos para realizar una de las tareas administrativas más críticas: hacer una copia de seguridad de tus datos importantes desde un volumen y, igual de importante, restaurarlos. Esto proporciona una red de seguridad y es una habilidad esencial para cualquiera que ejecute aplicaciones con estado en Docker.
A medida que crezca tu pericia, nos aventuraremos en territorio más avanzado. Veremos técnicas sofisticadas de Dockerfile que te ayudan a crear imágenes más pequeñas, seguras y eficientes. Una imagen optimizada se construye más rápido, consume menos espacio en disco y tiene una superficie de ataque menor, todo lo cual es crítico en un entorno de producción. Te mostraremos cómo estructurar tus Dockerfiles para aprovechar al máximo el mecanismo de caché de capas de Docker para construcciones más rápidas.
La automatización se extiende más allá de tu máquina local, y el desarrollo de software moderno está profundamente entrelazado con plataformas de CI/CD. Un capítulo dedicado te guiará a través del proceso de uso de GitHub Actions para automatizar la construcción y el envío de tus imágenes Docker a un registro. Esto cierra la brecha entre tu repositorio de código y tu entorno de despliegue, creando un flujo continuo desde el commit hasta la imagen de contenedor.
También exploraremos cómo los scripts pueden adaptarse específicamente para entornos de desarrollo. Esto incluye scripts que configuran pilas de aplicaciones complejas, gestionan diferentes contextos de Docker para cambiar entre daemons Docker locales y remotos, y automatizan la creación de redes personalizadas para asegurar que tus contenedores puedan comunicarse de la forma que tu aplicación requiere. Estos scripts ayudan a imponer la consistencia en un equipo de desarrolladores, asegurando que todos trabajen en un entorno idéntico.
La interacción con los contenedores no se detiene una vez que están en ejecución. Investigaremos cómo escribir scripts para comprobaciones de salud que monitoricen el estado de tus aplicaciones y cómo crear scripts de punto de entrada personalizados que hagan tus contenedores más flexibles y configurables en tiempo de ejecución. Incluso aprenderás a saltarte la CLI e interactuar directamente con el motor de Docker usando su API, abriendo un mundo completamente nuevo de posibilidades de automatización con lenguajes como Python.
La seguridad es una preocupación primordial en cualquier entorno, y Docker no es una excepción. Un capítulo dedicado se centrará en el scripting para el manejo seguro de secretos, un aspecto crítico del despliegue de aplicaciones que necesitan conectarse a bases de datos u otros servicios protegidos. Veremos diferentes estrategias para proporcionar información sensible a tus contenedores sin codificarla en tus imágenes o scripts, que es un antipatrón común pero peligroso.
Finalmente, uniremos todo abordando flujos de trabajo complejos del mundo real. Recorreremos el scripting del despliegue de una aplicación completa (full-stack), desde la construcción de las imágenes hasta el lanzamiento de los servicios interconectados. También cubriremos scripts para tareas administrativas como la gestión de usuarios en un entorno Docker compartido, el apagado y eliminación grácil de contenedores para asegurar cierres limpios, y la creación de herramientas personalizadas para inspeccionar y formatear información de contenedores para obtener la salida exacta que necesitas.
La filosofía detrás de los scripts de este libro es la practicidad y la adaptabilidad. Están escritos para ser lo más claros y directos posible, con comentarios que explican las partes más complejas. Sin embargo, no pretenden ser artefactos inmutables. Te animamos a tomarlos, modificarlos, romperlos y reconstruirlos para que se ajusten perfectamente a tus necesidades. El objetivo no es solo proporcionarte una biblioteca de scripts, sino empoderarte con el conocimiento para crear los tuyos propios.
Para aprovechar al máximo este libro, te animo a ser un lector activo. No solo leas el texto; abre tu terminal y ejecuta los scripts. Experimenta con los comandos e intenta modificar el código para ver qué pasa. La mejor forma de aprender scripting es haciéndolo, y la mejor forma de entender una herramienta es usándola. Configura un entorno Docker local seguro donde puedas experimentar libremente sin temor a romper nada crítico.
El viaje desde un usuario manual de Docker, comando a comando, hasta un maestro de la automatización es gratificante. Te ahorrará tiempo, reducirá errores y, en última instancia, te permitirá centrarte en los aspectos más interesantes y creativos de tu trabajo. La capacidad de encapsular un proceso complejo en un único script ejecutable es un superpoder en el mundo del desarrollo de software y las operaciones.
Este libro es tu guía para desarrollar ese superpoder. Es hora de ir más allá de la monotonía de la escritura repetitiva y abrazar la elegancia de la automatización. Dejemos de escribir y empecemos a scriptear.
CAPÍTULO UNO: Primeros pasos con Docker: Comandos esenciales.
Antes de poder componer una sinfonía, primero se debe aprender a tocar las notas individuales. En el mundo de la automatización con Docker, nuestras notas son los comandos de la interfaz de línea de comandos (CLI). Estos son los verbos fundamentales que nos permiten comunicar nuestras intenciones al daemon de Docker, el motor que impulsa nuestro mundo contenerizado. Si bien el objetivo final de este libro es entrelazar estos comandos en scripts elegantes y potentes, ese viaje debe comenzar con una comprensión sólida de los comandos en sí mismos. Este capítulo es su caja de herramientas, un recorrido guiado por las herramientas esenciales a las que recurrirá una y otra vez. Dominar estos comandos es el primer paso, y el más crítico, para volverse competente en Docker y, por extensión, en su automatización.
Exploraremos el ciclo de vida completo de un contenedor, desde encontrar el paquete de software adecuado en un registro público hasta ejecutarlo, inspeccionarlo, gestionar su estado y, finalmente, limpiarlo. Cada comando es un bloque de construcción. Comprender no solo qué hace un comando, sino también sus diversas opciones y el contexto en el que es más efectivo, es fundamental. Estas son las herramientas que usará para construir los flujos de trabajo automatizados sofisticados en los capítulos venideros. Piense en esto como su entrenamiento fundamental, asegurando que su vocabulario sea robusto antes de empezar a escribir poesía.
Nuestro viaje comienza donde lo hacen la mayoría de los flujos de trabajo de Docker: con una imagen. Una imagen es un plano, una plantilla de solo lectura que contiene la aplicación, sus bibliotecas y sus dependencias. Estas imágenes suelen almacenarse en un registro, que es un repositorio para almacenarlas y distribuirlas. El registro público más común es Docker Hub. Lo primero que a menudo necesitará hacer es encontrar la imagen oficial para el software que desea utilizar. Para ello, el comando docker search es un punto de partida útil, aunque básico. Consulta Docker Hub en busca de imágenes que coincidan con su término de búsqueda.
Por ejemplo, si quisiera encontrar imágenes relacionadas con el popular servidor web Nginx, ejecutaría:
docker search nginx
La salida proporciona una lista de imágenes con columnas para el nombre, una breve descripción, el número de estrellas (una métrica aproximada de popularidad) y si la imagen es oficial. Las imágenes oficiales son un conjunto curado de repositorios de Docker, que proporcionan un punto de partida verificado y bien documentado para software común. Casi siempre es una práctica recomendada utilizar la imagen oficial si existe una disponible, ya que se mantienen teniendo en cuenta la seguridad y la estabilidad.
Una vez que ha identificado la imagen que desea usar, como la imagen oficial nginx, necesita traerla del registro a su máquina local. Este es el trabajo del comando docker pull. Este comando descarga las capas de la imagen necesarias para ensamblar la imagen completa en su sistema. La sintaxis es sencilla, requiere el nombre de la imagen y, opcionalmente, una etiqueta. Una etiqueta se usa para versionar una imagen, como 1.21 o latest. Si no se especifica ninguna etiqueta, Docker usa por defecto la etiquetada como latest.
Para descargar la imagen oficial de Nginx, ejecutaría:
docker pull nginx
Esto es equivalente a docker pull nginx:latest. Para descargar una versión específica, especificaría la etiqueta así: docker pull nginx:1.21. Usar etiquetas de versión específicas en lugar de latest es una práctica crucial para crear entornos reproducibles y scripts confiables. La etiqueta latest puede actualizarse en cualquier momento por el mantenedor de la imagen, lo que significa que su script podría comportarse de manera diferente de un día para otro. Fijar una versión específica asegura que siempre está trabajando con el mismo software exacto. Después de descargar, puede ver todas las imágenes en su máquina local con el comando docker images.
Con una imagen descargada en su máquina, tiene el plano. El siguiente paso lógico es usar ese plano para construir algo real: un contenedor. Un contenedor es una instancia ejecutable de una imagen. El comando para crear e iniciar un contenedor es docker run, probablemente el comando más importante y rico en características de la CLI de Docker. Su forma básica es simple, pero su poder reside en la multitud de banderas que pueden usarse para configurar cómo se ejecuta el contenedor.
La ejecución más simple posible de este comando es con una imagen como hello-world, diseñada para este mismo propósito.
docker run hello-world
Cuando ejecuta esto, se desarrolla una secuencia de eventos. Docker verifica si la imagen hello-world está presente en su sistema local. Si no lo está, la descarga automáticamente de Docker Hub. Luego crea un nuevo contenedor a partir de esa imagen. Ejecuta el comando incrustado dentro de la imagen, que en este caso imprime un mensaje amistoso en su terminal. Finalmente, una vez que el comando termina, el contenedor se detiene. Este ejemplo simple demuestra la función central de crear y ejecutar un contenedor.
Para la mayoría de las aplicaciones del mundo real, sin embargo, necesitará más control. Querrá ejecutar contenedores en segundo plano, interactuar con ellos, exponerlos a su red y darles datos persistentes. Aquí es donde entran en juego las banderas para docker run. Empecemos distinguiendo entre dos modos principales de operación: interactivo y desapegado (detached).
Un contenedor interactivo es aquel al que conecta su terminal, permitiéndole ejecutar comandos dentro de él directamente. Esto se logra con las banderas -it. La bandera -i mantiene la entrada estándar (STDIN) abierta, y la bandera -t asigna un pseudo-TTY, que esencialmente le da una línea de comandos dentro del contenedor. Esto es perfecto para explorar una imagen o realizar una tarea puntual. Por ejemplo, para ejecutar un contenedor de Ubuntu y obtener un shell bash dentro de él, usaría:
docker run -it ubuntu /bin/bash
Su indicador de terminal cambiaría, y ahora estaría ejecutando comandos dentro del contenedor de Ubuntu. Esto es increíblemente útil para depuración o desarrollo. Cuando escribe exit, el proceso bash termina y el contenedor se detiene.
El modo alternativo es el modo desapegado, especificado con la bandera -d. Este es el caballo de batalla para ejecutar servicios de larga duración como servidores web, bases de datos o APIs. Cuando ejecuta un contenedor en modo desapegado, Docker inicia el contenedor y luego le devuelve el control de su terminal host, dejando el contenedor ejecutándose en segundo plano. El comando imprime el ID único del contenedor recién creado como confirmación. Por ejemplo, para iniciar un servidor web Nginx en segundo plano:
docker run -d nginx
Ahora tiene un servidor web ejecutándose, pero ¿cómo accede a él? Por defecto, los contenedores están aislados de la red del host. Para exponer un servicio que se ejecuta dentro de un contenedor, debe mapear un puerto de la máquina host a un puerto dentro del contenedor usando la bandera -p. El formato es -p [puerto_host]:[puerto_contenedor]. Si queremos acceder a nuestro servidor Nginx en el puerto 8080 de nuestra máquina local, lo mapearíamos al puerto 80 dentro del contenedor, que es el puerto predeterminado en el que Nginx escucha.
docker run -d -p 8080:80 nginx
Ahora, si abre un navegador web y navega a http://localhost:8080, verá la página de bienvenida predeterminada de Nginx, servida desde dentro de su contenedor. Este mapeo de puertos es fundamental para hacer que las aplicaciones contenerizadas sean útiles.
Cuando ejecuta un contenedor, Docker le asigna un nombre generado aleatoriamente, a menudo caprichoso, como vigilant_murdock o dreamy_bassi. Aunque divertidos, estos nombres no son útiles para la automatización. Si quiere referirse de forma fiable a un contenedor específico en un script, necesita darle un nombre predecible. La bandera --name le permite hacer precisamente esto. Un contenedor bien nombrado es el primer paso hacia un entorno manejable.
docker run -d -p 8080:80 --name my-web-server nginx
Ahora, en lugar de necesitar encontrar su nombre o ID aleatorio, puede simplemente referirse a este contenedor como my-web-server en comandos posteriores, lo cual es mucho más conveniente y esencial para escribir scripts robustos.
Otro concepto crítico es la persistencia de datos. El sistema de archivos dentro de un contenedor es efímero por defecto. Esto significa que si elimina el contenedor, cualquier dato creado o modificado dentro de él se pierde para siempre. Esto está bien para aplicaciones sin estado, pero es desastroso para cualquier cosa que necesite mantener estado, como una base de datos. Docker resuelve esto con volúmenes. Un volumen es un mecanismo para persistir los datos generados y utilizados por los contenedores de Docker. Profundizaremos en la gestión de volúmenes mediante scripts en el Capítulo 13, pero el uso básico con docker run es esencial saberlo ahora.
La bandera -v se usa para montar un volumen en un contenedor. Puede dejar que Docker gestione el volumen (un volumen con nombre) o mapear un directorio específico de su máquina host dentro del contenedor (un montaje de enlace o bind mount). Para una base de datos MySQL, podría querer persistir el directorio de datos:
docker run -d --name my-database -e MYSQL_ROOT_PASSWORD=mysecretpassword -v mysql-data:/var/lib/mysql mysql
En este comando, también hemos introducido la bandera -e, que establece una variable de entorno dentro del contenedor. Esta es una forma muy común de pasar detalles de configuración, como contraseñas o ajustes, a la aplicación que se ejecuta en el contenedor. La parte -v mysql-data:/var/lib/mysql le dice a Docker que cree un volumen con nombre llamado mysql-data (si no existe ya) y lo monte en la ruta /var/lib/mysql dentro del contenedor. Ahora, incluso si elimina el contenedor my-database, el volumen mysql-data permanecerá, y puede adjuntarlo a un nuevo contenedor para reanudar su trabajo.
Finalmente, para muchas tareas temporales, como ejecutar una suite de pruebas o un proceso de construcción, crea un contenedor, este realiza su acción y luego se detiene. Por defecto, este contenedor detenido sigue existiendo en su sistema. Con el tiempo, esto puede llevar a una cantidad significativa de desorden. La bandera --rm le dice a Docker que elimine automáticamente el contenedor en cuanto salga. Esta es una fantástica función de limpieza.
docker run --rm -it ubuntu echo "Este contenedor desaparecerá cuando termine."
Una vez que el comando echo se completa, el contenedor se elimina inmediata y automáticamente, dejando su sistema limpio. Usar --rm para contenedores de vida corta y de una sola tarea es una práctica recomendada que evita la acumulación de contenedores detenidos.
Una vez que tiene contenedores ejecutándose, particularmente en modo desapegado, necesita una forma de ver qué está pasando. El comando principal para esto es docker ps. Por sí solo, este comando enumera todos los contenedores en ejecución en su sistema. La salida es una tabla ordenada que muestra varias piezas de información útiles: el ID del contenedor, la imagen de la que fue creado, el comando que está ejecutando, cuándo fue creado, su estado actual, cualquier mapeo de puertos y su nombre.
Esta vista es crucial para obtener una visión rápida de su entorno activo. Sin embargo, solo cuenta parte de la historia. Para ver todos los contenedores, incluyendo los que se han detenido o salido, debe agregar la bandera -a.
docker ps -a
Este comando es su recurso para un inventario completo. Verá contenedores que salieron correctamente (Estado Exited (0)) y los que fallaron (por ejemplo, Exited (1)). Este es a menudo el primer paso para depurar por qué un contenedor no se está ejecutando como se esperaba.
Para propósitos de scripting, la salida tabular predeterminada de docker ps no siempre es ideal. Está diseñada para ojos humanos. Cuando necesita pasar una lista de contenedores a otro comando, a menudo solo quiere los IDs. La bandera -q (quiet/silencioso) modifica la salida para mostrar solo los IDs de los contenedores, uno por línea. Por ejemplo, para obtener una lista de todos los IDs de contenedores, en ejecución o detenidos:
docker ps -a -q
Esta salida puede usarse directamente en otros comandos. Por ejemplo, un patrón común para eliminar todos los contenedores detenidos es usar sustitución de comandos: docker rm $(docker ps -a -f "status=exited" -q). Aquí también hemos introducido la bandera -f (o --filter), que le permite acotar la lista basándose en ciertos criterios, en este caso, el estado del contenedor. Esta combinación de filtrado y salida silenciosa es una técnica poderosa que forma la base de muchos scripts de limpieza.
Saber simplemente que un contenedor se está ejecutando a menudo no es suficiente. Necesita ver su salida o interactuar con él. Para contenedores desapegados, que no tienen su salida conectada a su terminal, el comando docker logs es esencial. Obtiene los registros (salida estándar y error estándar) de un contenedor.
docker logs my-web-server
Esto mostrará todos los registros generados por el contenedor Nginx desde que se inició. Para un servicio que se ejecuta continuamente, podría querer ver los registros en tiempo real, similar al comando tail -f en Linux. La bandera -f (follow/seguir) para docker logs hace exactamente eso.
docker logs -f my-web-server
Su terminal ahora transmitirá los registros a medida que se generen, lo cual es invaluable para la monitorización en vivo y la depuración.
A veces necesita hacer más que solo ver registros; necesita ejecutar un comando dentro de un contenedor que ya se está ejecutando. Por ejemplo, podría querer inspeccionar un archivo de configuración en su contenedor Nginx en ejecución o verificar el contenido de una base de datos. Este es el trabajo del comando docker exec. Le permite "ejecutar" un comando en un contenedor en ejecución.
Para obtener un shell interactivo dentro de nuestro contenedor my-web-server en ejecución, usaría:
docker exec -it my-web-server /bin/bash
Esto se ve muy similar al comando docker run -it, pero la diferencia crucial es que docker exec se adjunta a un contenedor existente y en ejecución, mientras que docker run crea uno nuevo. Usar exec es la forma estándar de realizar tareas administrativas en un servicio en ejecución sin necesidad de detenerlo y reiniciarlo.
El ciclo de vida de un contenedor no se trata solo de creación; también se trata de control. Con frecuencia necesitará detener, iniciar y reiniciar sus contenedores. Los comandos para estas acciones son directos: docker stop, docker start y docker restart. El comando docker stop apaga un contenedor de forma grácil enviando primero una señal SIGTERM, permitiendo que la aplicación realice un apagado limpio. Si no se detiene dentro de un período de gracia (típicamente 10 segundos), Docker sigue con una señal SIGKILL para terminarlo forzosamente.
docker stop my-web-server
Una vez que un contenedor se detiene, ya no aparece en la salida predeterminada de docker ps, pero sigue existiendo y puede verse con docker ps -a. Para devolverlo a la vida, usa docker start.
docker start my-web-server
El contenedor se reanudará con su configuración anterior, incluyendo su nombre y cualquier volumen adjunto. El comando docker restart es simplemente un atajo conveniente que realiza una parada seguida de un inicio, lo cual es útil para aplicar cambios de configuración que requieren un reinicio del servicio.
Un entorno Docker bien mantenido es un entorno limpio. Con el tiempo, los contenedores detenidos y las imágenes sin usar pueden acumularse, consumiendo un espacio significativo en disco. Ya hemos visto la bandera --rm para docker run, pero también necesita comandos para limpiar manualmente los recursos existentes. El comando docker rm se usa para eliminar uno o más contenedores detenidos.
docker rm [id_o_nombre_contenedor]
No puede eliminar un contenedor en ejecución a menos que use la bandera -f (force/forzar), pero el enfoque más limpio es siempre detenerlo primero y luego eliminarlo. También puede pasar una lista de IDs de contenedores para eliminar varios contenedores a la vez, una técnica que, como se mencionó, es perfecta para scripting.
De manera similar, las imágenes pueden ocupar incluso más espacio que los contenedores. El comando docker rmi se usa para eliminar una o más imágenes. Una imagen no puede eliminarse si está siendo usada actualmente por un contenedor, incluso uno detenido. Debe eliminar primero los contenedores dependientes antes de poder eliminar la imagen en la que se basan.
docker rmi nginx:1.21
Estos comandos de limpieza manual son efectivos, pero también son candidatos primordiales para la automatización. Capítulos posteriores le mostrarán cómo construir scripts que encuentren y eliminen inteligentemente los recursos sin usar, ahorrándole tiempo y espacio en disco.
Finalmente, hay un comando que actúa como una herramienta universal para la inspección profunda: docker inspect. Este comando puede usarse en contenedores, imágenes, volúmenes y redes. Devuelve un array JSON detallado que contiene una gran cantidad de información sobre el objeto Docker especificado. La salida puede resultar abrumadora al principio, pero es un recurso increíblemente potente para la automatización.
docker inspect my-web-server
Esto imprimirá un gran objeto JSON en la pantalla, detallando todo sobre el contenedor: su estado, su configuración, sus ajustes de red (incluyendo su dirección IP interna), sus montajes de volumen y mucho más.
El verdadero poder de docker inspect para scripting se desbloquea con su bandera --format. Esta bandera le permite proporcionar una plantilla Go para extraer piezas específicas de información de la salida JSON. En lugar de analizar un archivo JSON enorme con una herramienta como jq, puede pedirle a Docker que le dé solo el dato que necesita. Por ejemplo, para obtener solo la dirección IP interna de un contenedor:
docker inspect --format='{{.NetworkSettings.IPAddress}}' my-web-server
Esta capacidad de consultar con precisión el estado y la configuración de cualquier objeto Docker es lo que convierte a docker inspect en una piedra angular del scripting avanzado. Puede usarlo para obtener información dinámica, como la dirección IP de un contenedor, e introducirla en otros comandos o archivos de configuración, creando una automatización verdaderamente dinámica e inteligente.
Estos comandos —pull, run, ps, logs, exec, stop, rm, rmi y inspect— forman el vocabulario central de Docker. Son las herramientas esenciales que usará todos los días. Al comprender sus funciones y opciones, ha construido la base necesaria. Ahora puede gestionar manualmente el ciclo de vida completo de un contenedor. Con esta sólida comprensión de los bloques de construcción individuales, estamos listos para dar el siguiente paso: definir nuestros propios planos para aplicaciones aprendiendo a construir un Dockerfile.
This is a sample preview. The complete book contains 27 sections.