Publicado en

Docker Compose: gestiona múltiples contenedores

Fragmento de docker-compose.yml con tres servicios (web, api, db) sobre fondo oscuro

Una aplicación real raramente es un solo proceso. Necesitas la aplicación, una base de datos, quizás un caché, un proxy inverso. Levantarlos por separado con docker run, pasarles las variables correctas, conectarlos en la misma red… se convierte en algo tedioso de repetir. Docker Compose resuelve esto con un solo archivo de configuración y un solo comando.

Qué es Docker Compose

Docker Compose es una herramienta que permite definir y ejecutar aplicaciones multi-contenedor. Describes todos los servicios, redes y volúmenes en un archivo docker-compose.yml y los arrancas con docker compose up. Compose gestiona el ciclo de vida completo: crear, arrancar, parar y eliminar todos los recursos de la aplicación.

Estructura del docker-compose.yml

Estructura completa del docker-compose.yml con servicios, opciones de build, ports, depends_on, environment y volumes explicados
services:
  web:
    build: .
    ports:
      - "80:3000"
    depends_on:
      - db
    environment:
      DB_HOST: db
      DB_PORT: 5432
    restart: unless-stopped
 
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: miapp
      POSTGRES_PASSWORD: secreto
    volumes:
      - pgdata:/var/lib/postgresql/data
 
  redis:
    image: redis:7-alpine
 
volumes:
  pgdata:

Cada clave de services define un contenedor. Los servicios se comunican entre sí usando el nombre del servicio como hostname: el servicio web accede a la base de datos en db:5432, no en localhost. Compose crea automáticamente una red interna que conecta todos los servicios del mismo archivo.

depends_on indica que un servicio debe arrancar antes que otro. Ojo: solo espera a que el contenedor esté en pie, no a que el proceso dentro esté listo. Para esperar a que PostgreSQL esté listo para aceptar conexiones necesitas un healthcheck o un script de espera.

Volúmenes: datos que persisten

Sin volúmenes, cuando paras y eliminas un contenedor pierdes todos sus datos. Un volumen desacopla el almacenamiento del ciclo de vida del contenedor.

volumes:
  pgdata:      # volumen gestionado por Docker
 
# O un bind mount (carpeta del host)
volumes:
  - ./data:/var/lib/postgresql/data   # host:contenedor

Los volúmenes gestionados por Docker viven en /var/lib/docker/volumes/. Los bind mounts montan una carpeta del host directamente, lo que facilita el desarrollo porque los cambios en el código son visibles inmediatamente.

Variables de entorno y secretos

services:
  api:
    image: mi-api
    env_file:
      - .env          # carga variables desde un archivo .env
    environment:
      NODE_ENV: production
      DB_HOST: db     # sobreescribe lo que haya en .env

Comandos del día a día

Referencia de comandos Docker Compose organizados en ciclo de vida (up, down, restart, pull) y diagnóstico (ps, logs, exec, top)
docker compose up -d          # arranca en background
docker compose up --build     # reconstruye imágenes y arranca
docker compose down           # para y elimina contenedores y redes
docker compose down -v        # también elimina volúmenes
docker compose logs -f api    # logs en tiempo real del servicio api
docker compose exec db psql   # abre psql dentro del contenedor db
docker compose ps             # estado de todos los servicios
docker compose restart web    # reinicia solo el servicio web

Cuando el proyecto crece y el número de réplicas, redes y configuraciones se multiplica, Compose empieza a quedarse corto. El siguiente escalón son los orquestadores como Kubernetes, pero para la gran mayoría de proyectos, Compose es todo lo que necesitas. Lo que sí conecta directamente con Compose es el CI/CD: automatizar la construcción, prueba y despliegue de estos contenedores cada vez que haces un push al repositorio.