Zademy

Guía Completa de Docker y Docker Compose: Comandos y Mejores Prácticas

Docker; DevOps; Contenedores; Guía; CLI
1500 palabras

Guía Completa de Docker y Docker Compose: Comandos y Mejores Prácticas

Conceptos Fundamentales de Docker

Docker es un sistema de código abierto que facilita el desarrollo, despliegue y ejecución de aplicaciones mediante la contenedorización. Resuelve problemas de compatibilidad al empaquetar una aplicación y sus dependencias en unidades autónomas y portátiles que se ejecutan consistentemente en cualquier entorno.

Componentes Clave

  • Imágenes (Images): Son paquetes ejecutables de software ligeros, autónomos que contienen todo lo necesario para ejecutar una aplicación (código, runtime, bibliotecas, configuraciones). Son la plantilla virtualizada para crear contenedores.

  • Contenedores (Containers): Son la instancia de tiempo de ejecución de una imagen de Docker. Aislan el software de su entorno, permitiendo ejecutar muchos simultáneamente en un host.

  • Docker Hub: Es un servicio proporcionado por Docker para encontrar y compartir imágenes de contenedores.

Comandos CLI de Docker (Básico)

TareaComando CLIDescripción
Imágenes
Construir una Imagendocker build -t <nombre_imagen> .Construye una imagen a partir de un Dockerfile en el directorio actual.
Construir sin cachédocker build -t <nombre_imagen> . --no-cacheFuerza la reconstrucción sin usar la caché.
Listar Imágenesdocker imagesMuestra todas las imágenes locales.
Eliminar una Imagendocker rmi <nombre_imagen>Elimina una imagen local.
Eliminar Imágenes no usadasdocker image pruneElimina todas las imágenes no usadas.
Publicar en Docker Hubdocker push <usuario>/<nombre_imagen>Sube una imagen a Docker Hub.
Contenedores
Ejecutar Contenedor (con nombre)docker run --name <nombre_contenedor> <nombre_imagen>Crea y ejecuta un contenedor a partir de una imagen.
Ejecutar en Segundo Planodocker run -d <nombre_imagen>Ejecuta el contenedor en modo detached (segundo plano).
Ejecutar y Publicar Puertosdocker run -p <puerto_host>:<puerto_contenedor> <nombre_imagen>Mapea un puerto del contenedor al host.
Listar Contenedores (Corriendo)docker psMuestra los contenedores actualmente en ejecución.
Listar Todos (Corriendo y Detenidos)docker ps --allMuestra todos los contenedores, independientemente de su estado.
Iniciar/Detener/Reiniciardocker start|stop|restart <nombre_contenedor>Inicia o detiene un contenedor existente. docker stop envía una señal SIGTERM para un apagado ordenado.
Eliminar un Contenedordocker rm <nombre_contenedor>Elimina un contenedor detenido.
Entrar al Contenedordocker exec -it <nombre_contenedor> shAbre un shell interactivo dentro de un contenedor en ejecución.
Ver Logsdocker logs -f <nombre_contenedor>Muestra y sigue los logs del contenedor.
Inspeccionar Contenedordocker inspect <nombre_contenedor>Muestra detalles del contenedor, típicamente en formato JSON.
Monitorizar Recursosdocker statsMuestra estadísticas de uso de recursos en tiempo de ejecución.

Docker Avanzado: Buenas Prácticas en Imágenes y Seguridad

Construcciones Multi-Etapa (Multi-stage Builds)

Las construcciones multi-etapa optimizan los Dockerfiles manteniéndolos legibles. Permiten crear una imagen de producción pequeña y segura que solo contiene el binario o los artefactos necesarios, sin incluir las herramientas de desarrollo.

  • Uso: Se usan múltiples instrucciones FROM, cada una iniciando una nueva etapa.
  • Copia Selectiva: Se utiliza COPY --from=<etapa> para copiar artefactos de una etapa previa.
  • Nombramiento de Etapas: Es mejor nombrar las etapas con FROM <imagen> AS <NOMBRE> para referenciarlas más fácilmente y evitar que se rompa la copia si se reordenan las instrucciones: COPY --from=build /bin/hello /bin/hello.
  • Depuración: Puedes construir solo hasta una etapa específica usando: docker build --target <etapa> -t hello ..
  • BuildKit: Es el builder recomendado, ya que solo procesa las etapas de las que depende el objetivo, a diferencia del legacy builder que procesa todas las etapas hasta el objetivo.

Seguridad en Imágenes y Contenedores

PrácticaDetalle
Imágenes BaseUtiliza imágenes oficiales o verificadas de fuentes fiables. Comienza con una imagen base mínima e incluye solo las dependencias esenciales para minimizar vulnerabilidades.
EscaneoEscanea imágenes y contenedores regularmente en busca de vulnerabilidades conocidas (ej. usando herramientas como Trivy o Docker Scout).
PrivilegiosSigue el principio del mínimo privilegio. Ejecuta los contenedores como usuarios no root.
Sistema de ArchivosUsa sistemas de archivos de solo lectura siempre que sea posible.
Firma de ContenidoHabilita Docker Content Trust (DCT) para asegurar que solo utilizas imágenes firmadas.

Docker Compose (Gestión de Aplicaciones Multi-Contenedor)

Docker Compose es una herramienta que simplifica la gestión de aplicaciones multi-contenedor. Permite definir y orquestar múltiples contenedores (servicios, redes, volúmenes) en un único archivo YAML, típicamente docker-compose.yml.

  • Diferencia clave con Docker: Docker gestiona contenedores individuales, mientras que Docker Compose coordina múltiples contenedores que trabajan juntos.
  • Uso Ideal: Es especialmente útil para entornos de desarrollo y pruebas donde se requiere una configuración rápida y fluida de múltiples servicios (ej. aplicación web, base de datos y frontend).
  • Versión V2: Se recomienda usar la versión más reciente. La V1 (con guion: docker-compose) ha dejado de recibir actualizaciones; la V2 usa docker compose (sin guion).

Estructura y Comandos Básicos de Compose

El archivo docker-compose.yml define la estructura:

# Nota: En las versiones más recientes de Docker Compose, la versión ya no es necesaria
# version: '3.8'  # Opcional en versiones modernas
services:
  service1: # Definición de contenedores/servicios
    # Configuración del servicio
networks:
  network1: # Configuración de redes personalizadas
    # Configuración de red
volumes:
  volume1: # Definición de volúmenes nombrados
    # Configuración de volumen
TareaComando CLI (V2)Descripción
Construir y Desplegardocker compose upConstruye y ejecuta los contenedores definidos en el yml.
Desplegar en Detacheddocker compose up -dDespliega y deja la aplicación corriendo en segundo plano.
Detener Aplicacióndocker compose stopDetiene los contenedores.
Detener y Eliminardocker compose downDetiene y elimina servicios y redes. No elimina volúmenes nombrados por defecto.
Eliminar con Volúmenesdocker compose down --volumes o -vFuerza la eliminación de servicios, redes y volúmenes nombrados.
Escalar Serviciodocker compose up --scale servicio=nAumenta la cantidad de contenedores (n) para un servicio específico.
Estado de Serviciosdocker compose psMuestra el estado actual de los contenedores.
Logsdocker compose logsMuestra los logs de los contenedores definidos.

Gestión de Datos Persistentes (Volúmenes)

Los volúmenes son esenciales para persistir datos entre contenedores y el host, asegurando que los datos no se pierdan al detener o reiniciar los contenedores.

  • Volúmenes Nombrados: Tienen un nombre definido por el usuario, facilitando su identificación y gestión. Se definen en la sección volumes del yml y luego se montan en el servicio.
  • Montaje de Host (Bind Mounts): Permite compartir directorios del host con el contenedor para facilitar el acceso y la edición de datos. Se usa la sintaxis: /ruta/en/el/host:/ruta/en/el/contenedor.
TareaComando CLI (Docker, aplica a volúmenes de Compose)
Listar Volúmenesdocker volume ls
Inspeccionar Volumendocker volume inspect <nombre_volumen>
Eliminar Volumendocker volume rm <nombre_volumen>
Limpiar Volúmenes no usadosdocker volume prune

Buenas Prácticas Avanzadas de Producción con Compose

Gestión de Secretos y Variables de Entorno

La separación de las configuraciones clave (como credenciales de base de datos y claves de API) del código de la aplicación permite un despliegue más flexible y seguro.

  • Riesgo: Nunca codifiques secretos (contraseñas, tokens) en los Dockerfiles o los expongas accidentalmente en las capas de la imagen.
  • Archivo de Entorno (env_file): Se recomienda almacenar las variables de entorno en un fichero .env y referenciarlo en el docker-compose.yml usando la directiva env_file: .env.
  • Seguridad: Este archivo .env debe ser excluido del repositorio de código (ej. usando .gitignore), permitiendo que los secretos se carguen en tiempo de ejecución sin exponerse en el gestor de versiones.

Redes y Seguridad de Acceso

  • Conectividad Interna: Por defecto, los contenedores definidos en Compose tienen conectividad entre ellos internamente.
  • Protección de Bases de Datos: Es una buena práctica de seguridad quitar la exposición de puertos de la base de datos en el yml (no hacer port binding al host). Aunque el proceso de la base de datos reclame el puerto, este no estará vinculado al Host, protegiendo así la base de datos de la exposición pública. Para acceder a ella, se puede entubar una conexión por SSH.

Límites de Recursos y Reinicios

Para entornos compartidos, es vital limitar los recursos que puede consumir una aplicación para evitar impactar a otras.

  • Limitación de Recursos (deploy: resources): Permite especificar los límites de uso de memoria, CPU o GPU en el servicio.
    • Límites (limits): Uso total que puede tener la aplicación (ej. cpus: 1, memory: 1GB).
    • Reservas (reservations): RAM y CPU que el contenedor reserva exclusivamente para su funcionamiento.
  • Política de Reinicio (restart_policy): Es crucial usar restart: always para asegurar que la aplicación arranque automáticamente si el servidor se reinicia.
    • Configuraciones más detalladas permiten definir condiciones (ej. on-failure), retrasos (delay), número máximo de intentos (max_attempts) y una ventana de tiempo (window) para los reinicios.

Health Checks (Comprobaciones de Salud)

Permiten definir una prueba continua que se lanza al contenedor para verificar que realmente está funcionando, y reiniciarlo si falla.

  • Configuración: Se pueden definir el interval (cada cuánto se lanza la prueba), retries (número de fallos antes de considerar caída), timeout (tiempo máximo de espera para la petición) y start_period (margen de tiempo al inicio para que la aplicación arranque).

Seguridad del Host y Buenas Prácticas Generales

Para mejorar la seguridad del servidor Linux donde corre Docker Engine:

  • Acceso Root Limitado: Limitar el acceso Root para el login (a menudo desactivado por defecto en Ubuntu Server).
  • Claves RSA: Se recomienda usar claves RSA (SSH keys) en lugar de contraseñas para iniciar sesión.
    • Puedes crear una clave SSH con ssh-keygen.
    • Puedes copiar la clave pública al servidor con ssh-copy-id <usuario>@<servidor>.
  • Prevención de Ataques de Fuerza Bruta: Instala Fail2Ban (apt install fail2ban). Esta aplicación usa reglas de firewall (como IP Tables) para bloquear IPs que realicen demasiados intentos fallidos contra el puerto SSH.
  • Mantenimiento: Actualiza Docker Engine y sus dependencias frecuentemente para mitigar vulnerabilidades.
  • Monitorización: Implementa un sistema de monitorización para registrar logs de las aplicaciones y detectar automáticamente caídas o falta de recursos en el servidor, además de usar docker stats para monitorear recursos.

Conclusión

Docker y Docker Compose son herramientas fundamentales en el desarrollo de software moderno. Dominar sus comandos y mejores prácticas no solo mejora la eficiencia del desarrollo, sino que también asegura despliegues más seguros y mantenibles en producción. La implementación correcta de estas prácticas permite crear aplicaciones escalables, portátiles y resilientes.


Para continuar tu aprendizaje en contenerización, te recomiendo explorar las estrategias de orquestación con Kubernetes o profundizar en las técnicas de optimización de imágenes para reducir aún más el tamaño y tiempo de inicio de tus aplicaciones.