Descripción general
Docker Compose define aplicaciones multi-contenedor en un único archivo YAML. Esta chuleta cubre la estructura de compose.yaml, cada clave de servicio, opciones de entorno y configuración, redes y volúmenes, la CLI completa, archivos override y perfiles. Todos los ejemplos apuntan a Docker Compose v2 (el plugin docker compose) y la Especificación de Compose; la clave version: heredada es obsoleta e ignorada.
Estructura de compose.yaml
La estructura básica de un archivo Compose:
services: # Define servicios contenerizados
volumes: # Define volúmenes nombrados
networks: # Define redes personalizadas
configs: # Define configs (para swarm, opcional)
secrets: # Define secretos (para swarm, opcional)
Servicios: claves básicas
| Clave | Propósito | Ejemplo |
|---|---|---|
image: <name>:<tag> |
Usar una imagen precompilada | image: nginx:1.27 |
build: <path> |
Construir una imagen desde un Dockerfile en la ruta dada | build: . o build: ./services/web |
build: { context: <path>, dockerfile: <file> } |
Construir con contexto y ruta Dockerfile explícitos | build: { context: ., dockerfile: Dockerfile.prod } |
build: { context: <path>, args: { VAR: value } } |
Pasar argumentos de construcción | build: { context: ., args: { NODE_ENV: production } } |
container_name: <name> |
Establecer el nombre del contenedor (no recomendado para escalado) | container_name: my_web_app |
restart: <policy> |
Política de reinicio: no, always, on-failure, unless-stopped |
restart: unless-stopped |
restart: on-failure:<max-retries> |
Reiniciar en fallo hasta N veces | restart: on-failure:5 |
Redes y puertos
| Clave | Propósito | Ejemplo |
|---|---|---|
ports: [<host>:<container>] |
Mapear puerto del contenedor al host | ports: ["8080:80"] |
ports: [<host-ip>:<host>:<container>] |
Mapear a una IP de host específica | ports: ["127.0.0.1:8080:80"] |
ports: [<container>] |
Exponer sin mapear al host | ports: ["8080"] |
expose: [<port>] |
Exponer puerto para comunicación interna (sin mapeo al host) | expose: ["8080"] |
networks: [<network>] |
Adjuntar servicio a redes personalizadas | networks: [frontend, backend] |
networks: <network>: { ipv4_address: <ip> } |
Asignar IP estática | networks: { backend: { ipv4_address: 172.20.0.2 } } |
hostname: <name> |
Establecer nombre de host del contenedor | hostname: db-server |
links: [<service>] |
Enlazar a otro servicio (heredado, usa redes en su lugar) | links: [db] |
dns: [<ip>] |
Establecer servidores DNS | dns: [8.8.8.8, 8.8.4.4] |
dns_search: [<domain>] |
Establecer dominios de búsqueda DNS | dns_search: [example.com] |
Entorno y configuración
| Clave | Propósito | Ejemplo |
|---|---|---|
environment: { VAR: value } |
Establecer variables de entorno en línea | environment: { DEBUG: "true", LOG_LEVEL: info } |
environment: [VAR=value] |
Establecer variables de entorno como lista | environment: [DEBUG=true, LOG_LEVEL=info] |
env_file: <file> |
Cargar variables de entorno desde un archivo | env_file: .env |
env_file: [<file1>, <file2>] |
Cargar desde múltiples archivos (archivos posteriores anulan anteriores) | env_file: [.env, .env.local] |
working_dir: <path> |
Establecer directorio de trabajo dentro del contenedor | working_dir: /app |
command: <command> |
Sobrescribir CMD desde Dockerfile | command: python -u app.py |
command: [<cmd>, <arg1>, <arg2>] |
Comando como lista (forma exec, preferida) | command: [python, -u, app.py] |
entrypoint: <cmd> |
Sobrescribir ENTRYPOINT desde Dockerfile | entrypoint: /bin/bash |
entrypoint: [<cmd>, <arg>] |
ENTRYPOINT como lista (forma exec, preferida) | entrypoint: [python, -u] |
stdin_open: true |
Mantener stdin abierto incluso si no está adjunto | stdin_open: true |
tty: true |
Asignar una pseudo-terminal | tty: true |
Almacenamiento: volúmenes y bind mounts
| Clave | Propósito | Ejemplo |
|---|---|---|
volumes: [<host>:<container>] |
Bind mount un directorio del host | volumes: [./data:/app/data] |
volumes: [<name>:<container>] |
Montar un volumen nombrado | volumes: [my_data:/app/data] |
volumes: { <container>: {} } |
Volumen anónimo | volumes: { /app/data: {} } |
volumes: { <container>: { ro: true } } |
Montar solo lectura | volumes: { /data: { ro: true } } |
volumes: { <container>: { consistency: <mode> } } |
Modo de consistencia (solo macOS/Windows) | volumes: { /data: { consistency: delegated } } |
tmpfs: [<path>] |
Montar un sistema de archivos temporal | tmpfs: [/tmp] |
Nota: Define volúmenes nombrados en el nivel superior:
volumes:
my_data:
driver: local
Límites de recursos
| Clave | Propósito | Ejemplo |
|---|---|---|
cpus: <float> |
Limitar núcleos de CPU (p. ej., 0.5 para medio núcleo) |
cpus: 2 |
cpu_shares: <int> |
Peso de compartir CPU (prioridad relativa) | cpu_shares: 512 |
mem_limit: <value> |
Limitar memoria (p. ej., 512m, 1g) |
mem_limit: 512m |
memswap_limit: <value> |
Limitar memoria + intercambio | memswap_limit: 1g |
mem_reservation: <value> |
Límite de memoria suave (permite exceder si hay espacio) | mem_reservation: 256m |
Verificaciones de salud
| Clave | Propósito | Ejemplo |
|---|---|---|
healthcheck: { test: [CMD, curl, -f, 'http://localhost/health'] } |
Definir comando de verificación de salud | (ver abajo) |
healthcheck: { test: CMD curl -f http://localhost/health } |
Verificación de salud como cadena | healthcheck: { test: CMD curl -f http://localhost/health } |
healthcheck: { test: CMD-SHELL, 'pg_isready -U postgres' } |
Verificación de salud con shell | (ver abajo) |
healthcheck: { interval: 30s } |
Con qué frecuencia ejecutar la verificación (predeterminado: 30s) | interval: 30s |
healthcheck: { timeout: 5s } |
Tiempo de espera para la verificación (predeterminado: 30s) | timeout: 5s |
healthcheck: { start_period: 10s } |
Período de gracia antes de la primera verificación (predeterminado: 0s) | start_period: 10s |
healthcheck: { retries: 3 } |
Fallos consecutivos antes de marcar como no saludable (predeterminado: 3) | retries: 3 |
healthcheck: disable: true |
Desactivar verificación de salud (si se hereda de imagen) | disable: true |
Ejemplo completo:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
Dependencias y orden de inicio
| Clave | Propósito | Ejemplo |
|---|---|---|
depends_on: [<service>] |
Esperar a que se inicien los servicios (sin verificación de disponibilidad) | depends_on: [db, cache] |
depends_on: { <service>: { condition: service_started } } |
Esperar a que se inicie el servicio | depends_on: { db: { condition: service_started } } |
depends_on: { <service>: { condition: service_healthy } } |
Esperar a que el servicio sea saludable | depends_on: { db: { condition: service_healthy } } |
depends_on: { <service>: { condition: service_completed_successfully } } |
Esperar a que el servicio se complete correctamente (trabajos únicos) | depends_on: { migration: { condition: service_completed_successfully } } |
Precaución: condition: service_healthy requiere que el servicio tenga healthcheck. Sin él, la condición falla inmediatamente.
Ejemplo completo:
services:
web:
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
Seguridad: secretos y configs
| Clave | Propósito | Ejemplo |
|---|---|---|
secrets: [<name>] |
Montar archivo secreto en /run/secrets/<name> |
secrets: [db_password] |
configs: [<name>] |
Montar archivo de config en / |
configs: [nginx_config] |
Definición en el nivel superior:
secrets:
db_password:
file: ./secrets/db_password.txt
configs:
nginx_config:
file: ./nginx.conf
Acceso en contenedor:
# En shell: cat /run/secrets/db_password
Perfiles
Los perfiles permiten incluir servicios condicionalmente.
services:
web:
image: nginx:latest
# Siempre incluido
debug:
image: busybox:latest
profiles: [debug]
# Solo incluido con --profile debug
monitoring:
image: prom/prometheus:latest
profiles: [monitoring, prod]
# Incluido con --profile monitoring O --profile prod
Uso:
docker compose up # Incluir solo servicios sin perfiles
docker compose --profile debug up # Incluir web + debug
docker compose --profile monitoring up # Incluir web + monitoring
docker compose --profile debug --profile monitoring up # Incluir los tres
Redes (nivel superior)
networks:
frontend:
driver: bridge
backend:
driver: bridge
driver_opts:
com.docker.network.bridge.name: br0
Uso de servicio:
services:
web:
networks: [frontend, backend]
db:
networks: [backend]
Volúmenes (nivel superior)
volumes:
db_data:
driver: local
shared_cache:
driver: local
driver_opts:
type: tmpfs
device: tmpfs
Archivos override
Docker Compose carga automáticamente docker-compose.override.yaml y lo fusiona con compose.yaml.
compose.yaml (producción):
services:
web:
image: myapp:latest
environment:
LOG_LEVEL: warn
docker-compose.override.yaml (desarrollo local):
services:
web:
build: .
ports:
- "8000:8000"
environment:
LOG_LEVEL: debug
Resultado cuando se ejecuta docker compose up:
– Imagen se construye desde ./Dockerfile (sobrescribe image: myapp:latest)
– Puerto 8000 se expone en el host
– LOG_LEVEL se establece a debug
– Mapeo de puerto y LOG_LEVEL se fusionan
Archivo override explícito:
docker compose -f compose.yaml -f compose.prod.yaml up
Comandos CLI
| Comando | Propósito | Ejemplo |
|---|---|---|
docker compose up |
Crear e iniciar todos los servicios | docker compose up |
docker compose up -d |
Iniciar servicios en modo desasociado (fondo) | docker compose up -d |
docker compose up -d --scale web=3 |
Escalar un servicio a N réplicas | docker compose up -d --scale web=3 |
docker compose down |
Detener y eliminar todos los servicios, redes (mantiene volúmenes) | docker compose down |
docker compose down -v |
Detener y eliminar servicios, redes, Y volúmenes | docker compose down -v |
docker compose down --rmi all |
Eliminar servicios y eliminar todas las imágenes | docker compose down --rmi all |
docker compose down --remove-orphans |
Eliminar servicios no en el archivo Compose | docker compose down --remove-orphans |
docker compose ps |
Listar servicios en ejecución | docker compose ps |
docker compose logs |
Ver logs de todos los servicios | docker compose logs |
docker compose logs -f |
Transmitir logs continuamente (seguimiento) | docker compose logs -f |
docker compose logs -f <service> |
Transmitir logs desde un servicio | docker compose logs -f web |
docker compose logs --tail 50 <service> |
Mostrar últimas 50 líneas de un servicio | docker compose logs --tail 50 web |
docker compose exec <service> <command> |
Ejecutar un comando dentro de un servicio | docker compose exec web bash |
docker compose exec -it <service> bash |
Ejecutar bash interactivamente dentro de un servicio | docker compose exec -it db psql -U postgres |
docker compose exec -u <user> <service> <command> |
Ejecutar como un usuario específico | docker compose exec -u appuser web whoami |
docker compose pull |
Extraer las últimas imágenes para todos los servicios | docker compose pull |
docker compose build |
Construir todas las imágenes (si se especifica build:) |
docker compose build |
docker compose build --no-cache <service> |
Reconstruir sin caché | docker compose build --no-cache web |
docker compose start |
Iniciar servicios detenidos | docker compose start |
docker compose stop |
Detener servicios en ejecución | docker compose stop |
docker compose stop <service> |
Detener un servicio específico | docker compose stop web |
docker compose restart |
Reiniciar todos los servicios | docker compose restart |
docker compose restart <service> |
Reiniciar un servicio específico | docker compose restart web |
docker compose pause |
Pausar todos los servicios | docker compose pause |
docker compose unpause |
Reanudar servicios en pausa | docker compose unpause |
docker compose config |
Validar e imprimir la configuración final de Compose | docker compose config |
docker compose config --resolve-image-digests |
Resolver digests de imagen (útil para reproducibilidad) | docker compose config --resolve-image-digests |
docker compose watch |
Ver cambios y sincronizar/reconstruir servicios (Compose 2.22+) | docker compose watch |
docker compose version |
Mostrar versión de Docker Compose | docker compose version |
docker compose -f <file> <command> |
Especificar explícitamente un archivo Compose | docker compose -f docker-compose.prod.yaml up |
docker compose --project-name <name> <command> |
Usar un nombre de proyecto personalizado (predeterminado: nombre del directorio) | docker compose --project-name myapp up |
Patrones que reutilizarás
# Desarrollo con archivo override
# compose.yaml: configuración de producción
# docker-compose.override.yaml: ajustes de desarrollo local
# Base de datos con healthcheck y depends_on
services:
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
web:
depends_on:
db:
condition: service_healthy
# Aplicación de múltiples niveles
services:
web:
networks: [frontend, backend]
cache:
networks: [backend]
db:
networks: [backend]
# Cargar entorno desde archivo con sobrescrituras
services:
app:
env_file: .env
environment:
LOG_LEVEL: debug # Sobrescribir desde .env
# Perfiles para servicios opcionales
monitoring:
profiles: [monitoring]
debug:
profiles: [debug]
# Usar compose watch para recarga en vivo (Compose 2.22+)
# docker compose watch
watch:
- path: ./src
action: sync
target: /app/src
- path: ./requirements.txt
action: rebuild
Preguntas frecuentes
¿Cuál es la diferencia entre docker-compose.yml y compose.yaml?
Ambos son compatibles. Docker prefiere compose.yaml (sin guión). Ambos son equivalentes; elige una convención y adhiérete a ella. La documentación moderna usa compose.yaml.
¿Cómo establezco variables de entorno en Docker Compose?
Usa la clave environment en un servicio, o carga desde un archivo con env_file: .env. Las variables pueden estar codificadas, del shell del host (${VAR_NAME}), o desde archivos .env. Usa secretos para valores sensibles.
¿Cómo me aseguro de que un servicio se inicie antes que otro?
Usa depends_on: db: condition: service_healthy (requiere HEALTHCHECK). Solo para orden de inicio sin validación, usa el formulario corto depends_on: [db]; solo ordena el inicio y no espera a estar listo.
¿Cómo uso archivos override de Docker Compose?
Crea docker-compose.override.yaml en el mismo directorio. Compose lo carga automáticamente y lo fusiona con compose.yaml. Sobrescribe servicios específicos sin editar el archivo principal. Útil para desarrollo local vs. producción.
¿Qué son los perfiles de Docker Compose?
Los perfiles permiten incluir servicios condicionalmente. Establece profiles: [debug] en un servicio, luego usa docker compose --profile debug up para incluirlo. Útil para servicios de depuración opcionales o pilas de monitoreo.
Cómo se verificó esta guía
Escrita a mano a partir de la documentación oficial, con cada comando comprobado de nuevo y una segunda revisión antes de publicar. Última revisión: .
Fuentes oficiales consultadas para este artículo

