Cómo Configurar y Ejecutar Contenedores Docker Eficientemente

DockerBeginner
Practicar Ahora

Introducción

Este completo tutorial de Docker ofrece a desarrolladores y profesionales de TI una inmersión profunda en la tecnología de contenedores. Desde la comprensión de los conceptos centrales de Docker hasta técnicas prácticas de instalación y gestión, la guía cubre todo lo necesario para aprovechar las potentes capacidades de contenerización de Docker para el desarrollo y despliegue de software moderno.

Fundamentos de Docker

Introducción a la Tecnología de Contenedores

Docker es una plataforma potente para la tecnología de contenedores, que permite a los desarrolladores empaquetar, distribuir y ejecutar aplicaciones de manera eficiente. Los contenedores proporcionan entornos ligeros y portátiles que encapsulan el software y sus dependencias.

Conceptos Clave de Docker

graph TD
    A[Docker Engine] --> B[Container]
    A --> C[Image]
    A --> D[Dockerfile]
Concepto Descripción
Imagen Docker Plantilla de solo lectura que contiene el código de la aplicación y sus dependencias
Contenedor Instancia ejecutable de una imagen Docker
Docker Engine Entorno de ejecución para crear y gestionar contenedores

Verificación de la Instalación de Docker

Su entorno LabEx viene con Docker preinstalado. Verifiquemos la versión de Docker para asegurarnos de que está lista para usarse.

docker --version

La salida debería mostrar la versión de Docker, por ejemplo, Docker version 20.10.21, build baeda1f. Esto confirma que Docker está correctamente instalado y accesible.

Descarga de su Primera Imagen Docker

Una imagen Docker es una plantilla de solo lectura que contiene un conjunto de instrucciones para crear un contenedor. Descargaremos la imagen hello-world, que es una imagen mínima utilizada para probar las instalaciones de Docker.

docker pull hello-world

Este comando descarga la imagen hello-world de Docker Hub a su máquina local. Debería ver una salida que indica el progreso de la descarga y la confirmación de que la imagen ha sido descargada.

Ejecución de su Primer Contenedor Docker

Ahora que tenemos una imagen, ejecutemos un contenedor a partir de ella. Ejecutar un contenedor significa crear una instancia de la imagen.

docker run hello-world

Cuando ejecuta hello-world, Docker realiza las siguientes acciones:

  1. Comprueba si la imagen hello-world existe localmente. Si no es así, la descarga (lo cual ya hicimos).
  2. Crea un nuevo contenedor a partir de la imagen.
  3. Ejecuta el ejecutable dentro del contenedor.
  4. El contenedor imprime un mensaje "Hello from Docker!" y luego sale.

Esto demuestra el ciclo de vida básico de un contenedor Docker: descargar una imagen, ejecutar un contenedor y el contenedor ejecuta su tarea definida.

Listado de Imágenes Docker

Para ver las imágenes que ha descargado, utilice el comando docker images.

docker images

Este comando lista todas las imágenes Docker almacenadas en su sistema local, incluida la imagen hello-world que acabamos de descargar. Verá detalles como el repositorio, la etiqueta, el ID de la imagen, la fecha de creación y el tamaño.

Comprensión del Ciclo de Vida del Contenedor

Los contenedores proporcionan entornos aislados con su propio sistema de archivos, procesos e interfaces de red. Se pueden iniciar, detener, mover y eliminar rápidamente, lo que los hace ideales para microservicios y aplicaciones nativas de la nube.

Gestión de Archivos Dockerfile

Fundamentos del Dockerfile

Un Dockerfile es un documento de texto que contiene todos los comandos que un usuario podría llamar desde la línea de comandos para ensamblar una imagen. Define el entorno, las dependencias y la configuración para las aplicaciones contenerizadas.

graph TD
    A[Dockerfile] --> B[Comando de Construcción]
    B --> C[Imagen Docker]
    C --> D[Contenedor]

Creación de su Primer Dockerfile

Navegue al directorio docker_app, que se creó durante la fase de configuración. Este será nuestro directorio de trabajo para este laboratorio.

cd /home/labex/project/docker_app

Ahora, creemos un Dockerfile simple llamado Dockerfile en este directorio. Este Dockerfile creará una imagen basada en Ubuntu y le agregará un archivo de texto simple.

nano Dockerfile

Agregue el siguiente contenido al Dockerfile:

## Usa una imagen base oficial de Ubuntu
FROM ubuntu:22.04

## Establece el directorio de trabajo dentro del contenedor
WORKDIR /app

## Crea un archivo de texto simple
RUN echo "Hello from Dockerfile!" > /app/message.txt

## Comando para ejecutar cuando el contenedor se inicia
CMD ["cat", "/app/message.txt"]
  • FROM ubuntu:22.04: Esta instrucción especifica la imagen base para nuestra nueva imagen. Estamos utilizando Ubuntu 22.04.
  • WORKDIR /app: Esto establece el directorio de trabajo para cualquier instrucción RUN, CMD, ENTRYPOINT, COPY o ADD que siga en el Dockerfile. Si /app no existe, se creará.
  • RUN echo "Hello from Dockerfile!" > /app/message.txt: Esta instrucción ejecuta un comando dentro de la imagen durante el proceso de construcción. Aquí, crea un archivo llamado message.txt en el directorio /app con el contenido "Hello from Dockerfile!".
  • CMD ["cat", "/app/message.txt"]: Esta instrucción proporciona comandos predeterminados para un contenedor en ejecución. Cuando se ejecuta un contenedor a partir de esta imagen, ejecutará cat /app/message.txt, mostrando el contenido de nuestro archivo de mensaje.

Guarde el archivo presionando Ctrl+S y salga de nano presionando Ctrl+X.

Construcción de su Imagen Docker

Ahora que tenemos nuestro Dockerfile, construyamos la imagen Docker a partir de él. El comando docker build lee el Dockerfile y crea una imagen Docker.

docker build -t my-ubuntu-app .
  • docker build: El comando para construir una imagen Docker.
  • -t my-ubuntu-app: Esto etiqueta nuestra imagen con el nombre my-ubuntu-app. Puede elegir el nombre que desee.
  • .: Esto especifica el contexto de construcción, que es el conjunto de archivos en la PATH o URL especificada. El . indica que el directorio actual (/home/labex/project/docker_app) es el contexto de construcción. Docker buscará un Dockerfile en este directorio.

Verá una salida que muestra cada paso del proceso de construcción, correspondiente a las instrucciones de su Dockerfile.

Ejecución de su Contenedor Docker Personalizado

Después de construir la imagen con éxito, ejecutemos un contenedor a partir de ella para ver el contenido de message.txt.

docker run my-ubuntu-app

Este comando creará y ejecutará un nuevo contenedor a partir de su imagen my-ubuntu-app. Se ejecutará la instrucción CMD en su Dockerfile, y debería ver "Hello from Dockerfile!" impreso en su terminal.

Inspección del Sistema de Archivos del Contenedor

Para comprender mejor cómo se gestionan los archivos dentro de un contenedor, ejecutemos una sesión interactiva e inspeccionemos el archivo que creamos.

docker run -it my-ubuntu-app /bin/bash
  • -it: Esta bandera asigna un pseudo-TTY y mantiene STDIN abierto, lo que le permite interactuar con el contenedor.
  • my-ubuntu-app: El nombre de la imagen que queremos ejecutar.
  • /bin/bash: Esto anula la instrucción CMD en el Dockerfile y, en su lugar, ejecuta un shell Bash dentro del contenedor, proporcionándole un prompt de comandos.

Una vez dentro del contenedor, verá un nuevo prompt de comandos (por ejemplo, root@<container_id>:/app#). Ahora, puede listar los archivos y ver el contenido de message.txt.

ls -l
cat message.txt

Debería ver message.txt listado y su contenido mostrado. Para salir del contenedor, simplemente escriba exit.

exit

Esta sesión interactiva demuestra que el archivo message.txt se creó con éxito y es accesible dentro del sistema de archivos del contenedor.

Técnicas Avanzadas de Docker

Estrategias de Construcción Multi-Etapa (Multi-Stage Build)

Las construcciones multi-etapa son una característica potente que permite utilizar múltiples instrucciones FROM en su Dockerfile. Cada instrucción FROM puede usar una imagen base diferente, y cada instrucción FROM inicia una nueva etapa de construcción. Esto ayuda a optimizar la complejidad del Dockerfile y a reducir el tamaño de la imagen final separando los entornos de construcción y ejecución.

graph TD
    A[Etapa de Construcción] --> B[Compilar/Construir]
    B --> C[Etapa de Ejecución]
    C --> D[Imagen de Producción Mínima]

Preparación para una Construcción Multi-Etapa

Para este ejemplo, simularemos una aplicación simple que requiere un paso de construcción. Crearemos un archivo build_script.sh y un archivo final_app.txt.

Primero, asegúrese de estar en el directorio docker_app:

cd /home/labex/project/docker_app

Ahora, cree un script de construcción simple:

nano build_script.sh

Agregue el siguiente contenido a build_script.sh:

#!/bin/bash
echo "Ejecutando proceso de construcción..."
echo "Esta es la salida final de la aplicación." > /app/output/final_app.txt
echo "Construcción completa."

Guarde el archivo (Ctrl+S) y salga (Ctrl+X).

A continuación, cree un marcador de posición para el contenido final de nuestra aplicación. En un escenario real, esto sería generado por el proceso de construcción.

nano final_app.txt

Agregue el siguiente contenido a final_app.txt:

Este es un marcador de posición para la aplicación final.

Guarde el archivo (Ctrl+S) y salga (Ctrl+X).

Implementación de un Dockerfile Multi-Etapa

Ahora, modifiquemos nuestro Dockerfile para usar una construcción multi-etapa. Tendremos una etapa de "constructor" (builder) que ejecutará nuestro build_script.sh y luego una etapa de "producción" que solo copiará la salida necesaria de la etapa de constructor.

nano Dockerfile

Reemplace el contenido existente con lo siguiente:

## Etapa 1: Etapa de construcción (builder)
FROM ubuntu:22.04 AS builder

## Instalar bash para ejecutar el script
RUN apt-get update && apt-get install -y bash

## Establecer directorio de trabajo para la etapa de constructor
WORKDIR /build

## Copiar el script de construcción y hacerlo ejecutable
COPY build_script.sh .
RUN chmod +x build_script.sh

## Crear un directorio para la salida
RUN mkdir -p /build/output

## Ejecutar el script de construcción
RUN ./build_script.sh

## Etapa 2: Etapa de producción
FROM ubuntu:22.04

## Establecer directorio de trabajo para la etapa de producción
WORKDIR /app

## Copiar solo el artefacto necesario de la etapa de constructor
COPY --from=builder /build/output/final_app.txt .

## Comando para ejecutar cuando el contenedor se inicia
CMD ["cat", "final_app.txt"]
  • FROM ubuntu:22.04 AS builder: Esto inicia la primera etapa y la nombra builder.
  • RUN apt-get update && apt-get install -y bash: Instala bash en la etapa de constructor, que es necesario para ejecutar nuestro script.
  • WORKDIR /build: Establece el directorio de trabajo para la etapa de constructor.
  • COPY build_script.sh .: Copia nuestro script de construcción a la etapa de constructor.
  • RUN chmod +x build_script.sh: Hace que el script sea ejecutable.
  • RUN mkdir -p /build/output: Crea un directorio de salida en la etapa de constructor.
  • RUN ./build_script.sh: Ejecuta el script de construcción, que genera final_app.txt en /build/output.
  • FROM ubuntu:22.04: Esto inicia la segunda etapa (la etapa de producción). Utiliza una imagen ubuntu:22.04 nueva, lo que significa que no hereda nada de la etapa builder por defecto.
  • WORKDIR /app: Establece el directorio de trabajo para la etapa de producción.
  • COPY --from=builder /build/output/final_app.txt .: Esta es la instrucción clave para las construcciones multi-etapa. Copia final_app.txt del directorio /build/output de la etapa builder al directorio actual (/app) de la etapa de producción. Esto asegura que solo se incluya el artefacto final, manteniendo la imagen de producción pequeña.
  • CMD ["cat", "final_app.txt"]: El comando que se ejecutará cuando se inicie el contenedor de producción, mostrando el contenido del archivo copiado.

Guarde el archivo (Ctrl+S) y salga (Ctrl+X).

Construcción y Ejecución de la Imagen Multi-Etapa

Ahora, construyamos la nueva imagen utilizando nuestro Dockerfile multi-etapa.

docker build -t multi-stage-app .

Observe la salida de la construcción. Verá pasos tanto para la etapa builder como para la etapa final.

Después de que la construcción se complete, ejecute el contenedor para verificar que se muestra el contenido de final_app.txt.

docker run multi-stage-app

Debería ver "This is the final application output." impreso, lo que confirma que la construcción multi-etapa copió con éxito el artefacto de la etapa de construcción a la imagen final.

Limpieza de Recursos de Docker

Es una buena práctica limpiar los recursos de Docker (contenedores e imágenes) que ya no se necesitan para liberar espacio en disco.

Primero, liste todos los contenedores (incluidos los que han salido):

docker ps -a

Puede eliminar contenedores específicos por su ID o nombre:

docker rm $(docker ps -aq)

Este comando elimina todos los contenedores que han salido. docker ps -aq lista todos los IDs de contenedores, y docker rm los elimina.

A continuación, liste todas las imágenes:

docker images

Puede eliminar imágenes específicas por su ID o nombre. Tenga cuidado de no eliminar imágenes que todavía estén en uso por contenedores en ejecución.

docker rmi my-ubuntu-app multi-stage-app hello-world ubuntu:22.04

Este comando elimina las imágenes que creamos y utilizamos en este laboratorio. Si una imagen todavía está siendo utilizada por un contenedor, primero deberá eliminar el contenedor.

docker images

Este comando mostrará que las imágenes han sido eliminadas.

Esto concluye el laboratorio sobre los fundamentos de Docker y las técnicas avanzadas. Ha aprendido a crear Dockerfiles, construir imágenes, ejecutar contenedores y optimizar el tamaño de las imágenes utilizando construcciones multi-etapa.

Resumen

Al dominar los fundamentos de Docker, la gestión de Dockerfile y las técnicas avanzadas, los desarrolladores pueden crear entornos de software más eficientes, portátiles y escalables. Este tutorial le ha proporcionado habilidades prácticas en la creación de contenedores, la gestión de imágenes y las estrategias de despliegue, permitiéndole optimizar los flujos de trabajo de desarrollo y adoptar arquitecturas de aplicaciones nativas de la nube.