Docker Compose

En la entrada anterior se definió qué es un Dockerfile y cómo crear el documento adecuado para empaquetar una aplicación. Sin embargo, en un entorno real, las aplicaciones raramente funcionan de manera aislada.

Generalmente, el código (Backend) requiere conexión con una base de datos, una caché (como Redis) o un servidor web (como Nginx).

¿El problema? La ejecución manual de múltiples contenedores resulta compleja y propensa a errores. Gestionar varias terminales y comandos extensos hace necesario el uso de Docker Compose.

¿Qué es Docker Compose?

Si el Dockerfile define el «qué» (la imagen), Docker Compose define el «cómo» (la arquitectura).

Es una herramienta que permite describir múltiples contenedores, redes y volúmenes en un solo archivo de texto llamado docker-compose.yml. Mediante un único comando, es posible levantar toda la infraestructura necesaria para el funcionamiento del proyecto.

La estructura básica

Un archivo docker-compose.yml estándar organiza la infraestructura en tres bloques principales:

  1. Services: Los contenedores que se ejecutarán (aplicación, base de datos, etc.).
  2. Volumes: Ubicación para el almacenamiento persistente de datos, evitando su pérdida al detener el contenedor.
  3. Networks: Configuración de la comunicación entre los contenedores.

El problema: Configuración Rígida

Al igual que con el Dockerfile, es común crear un archivo Compose funcional pero inseguro y difícil de mantener.

A continuación, se presenta un ejemplo de una configuración no optimizada:

# ❌ EJEMPLO NO OPTIMIZADO
version: '3.8'

services:
  backend:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DB_PASSWORD=secret123
  
  database:
    image: postgres:latest
    environment:
      - POSTGRES_PASSWORD=secret123

¿Por qué es malo?

  • Seguridad Nula: Si subes este archivo a GitHub, acabas de regalar tus contraseñas al mundo.
  • Inestabilidad: Usar latest en bases de datos puede causar que, tras una actualización automática, tus datos dejen de ser compatibles y el contenedor no arranque.
  • Sin Persistencia: No hay volúmenes definidos. Si borras el contenedor database, pierdes todos tus usuarios y datos para siempre.

Estrategias de Optimización

Para profesionalizar nuestro flujo de trabajo, aplicaremos tres conceptos clave:

1. Variables de Entorno (.env)

Nunca escribas secretos en el código. Docker Compose busca automáticamente un archivo llamado .env en la misma carpeta. Úsalo para inyectar configuración dinámica sin exponerla.

2. Persistencia de Datos (Named Volumes)

Los contenedores son efímeros. Para evitar perder la información de tu base de datos cada vez que apagas el ordenador, usamos volúmenes nombrados.

3. Control de Dependencias (depends_on)

Tu aplicación web seguramente fallará si intenta conectarse a la base de datos antes de que esta haya terminado de encenderse. Usamos depends_on para controlar el orden de arranque.

El Resultado: Un Docker Compose Optimizado

Aplicando lo anterior, así se ve una arquitectura lista para trabajar en equipo:

# ✅ EJEMPLO OPTIMIZADO
version: '3.8'

services:
  # Servicio 1: Nuestra App (Python/Node/etc)
  api:
    build: .
    ports:
      - "${APP_PORT}:8000"
    environment:
      - DB_HOST=db_service 
      - DB_PASSWORD=${DB_PASS}
    depends_on:
      - db_service

  # Servicio 2: Base de Datos
  db_service:
    image: postgres:14-alpine
    restart: always
    environment:
      - POSTGRES_PASSWORD=${DB_PASS}
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

Conclusión

Docker Compose es la herramienta que te devuelve el control y la paz mental. Nos permite pasar de ejecutar comandos manuales a tener Infraestructura como Código.

  • Consistencia: Cualquier nuevo integrante del equipo solo tiene que hacer docker-compose up y todo funciona.
  • Seguridad: Tus secretos están aislados en tu entorno local.
  • Simplicidad: Un solo comando para gobernarlos a todos.