alltools.one
DevOps
2025-06-16
8 min
alltools.one Team
YAMLDockerDocker ComposeDevOpsContainers

YAML para Docker Compose: Patrones de Configuración y Consejos

Docker Compose usa YAML para definir aplicaciones multi-contenedor. Un docker-compose.yml bien estructurado es la diferencia entre un entorno de desarrollo fluido y horas depurando problemas de contenedores. Esta guía cubre patrones esenciales y errores comunes.

Estructura Básica

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./html:/usr/share/nginx/html
    depends_on:
      - api

  api:
    build: ./api
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://db:5432/myapp
    depends_on:
      - db

  db:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: myapp
      POSTGRES_PASSWORD: secret

volumes:
  pgdata:

Variables de Entorno

En Línea

services:
  api:
    environment:
      NODE_ENV: production
      PORT: "3000"
      DEBUG: "false"

Desde Archivo

services:
  api:
    env_file:
      - .env
      - .env.local  # Overrides .env values

Sustitución de Variables

Referencia variables de entorno del host:

services:
  api:
    image: myapp:${TAG:-latest}  # Default to "latest"
    environment:
      API_KEY: ${API_KEY}  # Required - fails if not set
      LOG_LEVEL: ${LOG_LEVEL:-info}  # Default to "info"

Redes

Redes Personalizadas

services:
  web:
    networks:
      - frontend
  api:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend

networks:
  frontend:
  backend:
    internal: true  # No external access

Los servicios en la misma red pueden comunicarse entre sí por nombre de servicio. El servicio db solo es accesible desde api, no desde web.

Mapeo de Puertos

ports:
  - "8080:80"         # host:container
  - "443:443"
  - "127.0.0.1:3000:3000"  # Bind to localhost only
  - "3000"            # Random host port

Volúmenes

Volúmenes con Nombre (Persistentes)

services:
  db:
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
    driver: local

Montajes Bind (Desarrollo)

services:
  api:
    volumes:
      - ./src:/app/src          # Source code
      - /app/node_modules       # Anonymous volume (prevent override)

El patrón de volumen anónimo (/app/node_modules) evita que el montaje bind del host sobreescriba las dependencias instaladas en el contenedor.

Verificaciones de Salud

services:
  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

  api:
    depends_on:
      db:
        condition: service_healthy

Esto asegura que api solo se inicie después de que db pase las verificaciones de salud — no solo cuando el contenedor arranque.

Campos de Extensión (Patrones DRY)

Usa campos con prefijo x- con anchors YAML para reducir la repetición:

x-common: &common
  restart: unless-stopped
  logging:
    driver: json-file
    options:
      max-size: "10m"
      max-file: "3"

x-env: &common-env
  TZ: UTC
  LOG_FORMAT: json

services:
  api:
    <<: *common
    build: ./api
    environment:
      <<: *common-env
      PORT: "3000"

  worker:
    <<: *common
    build: ./worker
    environment:
      <<: *common-env
      QUEUE: default

Para más información sobre anchors YAML, consulta nuestra guía de anchors y aliases YAML.

Compose Multi-Etapa

Desarrollo vs Producción

# docker-compose.yml (base)
services:
  api:
    build: ./api
    environment:
      DATABASE_URL: postgres://db:5432/myapp

# docker-compose.override.yml (dev - auto-loaded)
services:
  api:
    volumes:
      - ./api/src:/app/src
    environment:
      NODE_ENV: development
      DEBUG: "true"
    ports:
      - "3000:3000"
      - "9229:9229"  # Debug port

# docker-compose.prod.yml
services:
  api:
    environment:
      NODE_ENV: production
    deploy:
      replicas: 3
# Development (auto-loads override)
docker compose up

# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up

Errores Comunes

1. Números de Puerto Sin Comillas

# RISKY - YAML interprets 80:80 as a base-60 number
ports:
  - 80:80

# SAFE - always quote
ports:
  - "80:80"

2. Variables de Entorno Booleanas

# WRONG - YAML converts to boolean
environment:
  DEBUG: true  # Becomes Python True, not string "true"

# CORRECT - quote all env values
environment:
  DEBUG: "true"

3. Temporización de depends_on

depends_on solo espera a que el contenedor inicie, no a que esté listo:

# Container starts but DB might not be ready
depends_on:
  - db

# Wait for health check
depends_on:
  db:
    condition: service_healthy

Valida tus archivos Docker Compose con nuestro Validador YAML.

FAQ

¿Cuál es la diferencia entre docker-compose.yml y compose.yml?

Ambos nombres de archivo funcionan. compose.yml es la convención más reciente recomendada por Docker. docker-compose.yml es el nombre heredado. Docker Compose v2+ busca ambos, prefiriendo compose.yml si ambos existen. Para proyectos nuevos, usa compose.yml.

¿Debería usar Docker Compose en producción?

Docker Compose es excelente para desarrollo y despliegues simples. Para producción a escala, considera Docker Swarm (usa archivos Compose de forma nativa) o Kubernetes. La ventaja de Compose es que tu configuración de desarrollo informa directamente a producción, reduciendo las diferencias entre entornos.

Recursos Relacionados

Published on 2025-06-16
YAML for Docker Compose: Configuration Patterns and Tips | alltools.one