Docker Compose
Resumen de una línea
Cómo orquestar múltiples contenedores declarativamente con docker-compose.yaml: servicios, volúmenes, redes y ciclo de vida.
Información
- Fuente: Curso Docker 2024 - Módulo 6
- URL Plataforma: https://plataforma.josedomingo.org/pledin/cursos/docker2024/
- URL GitHub: https://github.com/josedom24/curso_docker_ow
- Líneas de contenido: 913
El Problema: Múltiples Contenedores
Sin Docker Compose (Manual)
# Crear red
docker network create app-net
# Base de datos
docker run -d \
--name mysql-db \
--network app-net \
-e MYSQL_ROOT_PASSWORD=secret \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# Cache
docker run -d \
--name redis-cache \
--network app-net \
redis:7
# API
docker run -d \
--name api \
--network app-net \
-p 3000:3000 \
mi-api:latest
# Web
docker run -d \
--name web \
--network app-net \
-p 80:80 \
mi-web:latestProblemas:
- ❌ Comandos largos y complejos
- ❌ Difícil de recordar
- ❌ Fácil de equivocarse
- ❌ No reproducible
- ❌ Difícil de documentar
Con Docker Compose (Declarativo)
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
volumes:
- mysql-data:/var/lib/mysql
redis:
image: redis:7
api:
image: mi-api:latest
ports:
- "3000:3000"
depends_on:
- mysql
- redis
web:
image: mi-web:latest
ports:
- "80:80"
volumes:
mysql-data:Ventajas:
- ✅ Todo en un archivo
- ✅ Reproducible
- ✅ Autodocumentado
- ✅ Fácil de versionar (git)
- ✅ Portable
Estructura Básica del compose.yaml
version: '3.8' # Versión de Compose
services: # Define los contenedores
nombre-servicio:
image: imagen:tag # O build: .
container_name: nombre
ports:
- "8080:80" # Puerto host:container
environment: # Variables de entorno
VAR: valor
DB_HOST: mysql
volumes: # Almacenamiento
- volumen-nombrado:/datos
- ./local:/container
depends_on: # Orden de inicio
- mysql
networks: # Redes
- app-net
restart: always # Policy de reinicio
volumes: # Volúmenes persistentes
volumen-nombrado:
driver: local
networks: # Redes personalizadas
app-net:
driver: bridgeSecciones Principales
1. services (Contenedores)
services:
mysql:
image: mysql:8.0
container_name: my-mysql
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: myapp
volumes:
- db-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- app-net
restart: unless-stoppedOpciones comunes:
image: Imagen Dockerbuild: Path a Dockerfile (en lugar de image)container_name: Nombre del contenedorenvironment: Variables de entornovolumes: Almacenamientoports: Mapeamiento de puertosdepends_on: Otros servicios que debe esperarnetworks: Redes a las que conectarrestart: Política de reinicio (always, unless-stopped, on-failure)command: Sobrescribir comandoworking_dir: Directorio de trabajouser: Usuario que ejecuta
2. volumes (Almacenamiento Persistente)
volumes:
mysql-data: # Volumen nombrado
driver: local
redis-data:
driver: localUsar en servicios:
services:
mysql:
volumes:
- mysql-data:/var/lib/mysql # Volumen nombrado
- ./backup:/backup # Bind mount3. networks (Redes)
networks:
app-net:
driver: bridge
ipam:
config:
- subnet: 192.168.1.0/24Usar en servicios:
services:
app:
networks:
- app-netComandos Docker Compose
docker compose up - Crear e Iniciar
# Iniciar en foreground
docker compose up
# Iniciar en background
docker compose up -d
# Reconstruir imágenes
docker compose up --build
# Forzar creación de nuevos contenedores
docker compose up --force-recreateQué hace:
- Crea red (si no existe)
- Crea volúmenes (si no existen)
- Crea contenedores
- Inicia contenedores
- Respeta
depends_on
docker compose ps - Ver Estado
docker compose ps
# Output:
NAME IMAGE SERVICE STATUS
mysql-db mysql:8.0 mysql Up 2 minutes
api mi-api:latest api Up 1 minutedocker compose logs - Ver Logs
# Logs de todos
docker compose logs
# Logs de un servicio
docker compose logs mysql
# Seguir en vivo (-f)
docker compose logs -f api
# Últimas 50 líneas
docker compose logs --tail 50 mysqldocker compose exec - Ejecutar en Contenedor
# Comando simple
docker compose exec mysql mysql -u root -p
# Shell interactivo
docker compose exec api bash
# Sin TTY (-T)
docker compose exec -T api npm testdocker compose stop - Parar
docker compose stop # Para todos
docker compose stop mysql # Para unodocker compose start - Reiniciar
docker compose start # Inicia todos paradosdocker compose down - Eliminar
# Elimina contenedores y redes (mantiene volúmenes)
docker compose down
# Elimina incluyendo volúmenes
docker compose down -v
# Elimina imagenes
docker compose down --rmi alldocker compose build - Construir Imágenes
# Construir todas
docker compose build
# Construir una
docker compose build api
# Sin cachés
docker compose build --no-cacheVariables de Entorno y Parámetros
Método 1: .env File
# archivo .env
MYSQL_ROOT_PASSWORD=secreto123
APP_PORT=3000
APP_DEBUG=true# compose.yaml
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}# Ejecutar
docker compose up -d
# Automáticamente lee .envMétodo 2: Variables Directas
services:
app:
image: mi-app:latest
environment:
DEBUG: "true"
PORT: "3000"Método 3: Desde Archivo
services:
app:
env_file:
- .env
- .env.localCasos de Uso Prácticos
Caso 1: WordPress + MariaDB
version: '3.8'
services:
wordpress:
image: wordpress:latest
ports:
- "80:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: user
WORDPRESS_DB_PASSWORD: password
volumes:
- wordpress:/var/www/html
depends_on:
- db
db:
image: mariadb:latest
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: user
MYSQL_PASSWORD: password
MYSQL_ROOT_PASSWORD: rootpass
volumes:
- db-data:/var/lib/mysql
volumes:
wordpress:
db-data:Usar:
docker compose up -d
# WordPress en http://localhostCaso 2: Node.js + MongoDB
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
MONGO_URL: mongodb://mongo:27017/myapp
depends_on:
- mongo
volumes:
- ./src:/app/src
mongo:
image: mongo:latest
volumes:
- mongo-data:/data/db
volumes:
mongo-data:Caso 3: Multi-tier con Redis
version: '3.8'
services:
frontend:
image: my-frontend:latest
ports:
- "80:80"
environment:
API_URL: http://api:3000
depends_on:
- api
api:
image: my-api:latest
ports:
- "3000:3000"
environment:
REDIS_URL: redis://redis:6379
DB_HOST: db
depends_on:
- db
- redis
db:
image: postgres:14
environment:
POSTGRES_PASSWORD: secret
volumes:
- db-data:/var/lib/postgresql/data
redis:
image: redis:7
volumes:
- redis-data:/data
volumes:
db-data:
redis-data:Dependencias: depends_on
Esperar Que Exista
services:
app:
depends_on:
- db
- redisQué hace:
- Inicia
dbyredisprimero - Luego inicia
app - ⚠️ No espera a que estén listos, solo que existan
Esperar Que Esté Listo (Healthcheck)
services:
db:
image: postgres:14
healthcheck:
test: ["CMD", "pg_isready"]
interval: 10s
timeout: 5s
retries: 5
app:
depends_on:
db:
condition: service_healthyBuild desde Dockerfile
services:
api:
build: . # Path a Dockerfile
# O con contexto específico:
build:
context: ./api
dockerfile: Dockerfile
args:
BUILD_ENV: productionCon variables:
services:
app:
build:
context: .
args:
NODE_ENV: ${APP_ENV}Restart Policies
restart: always # Siempre reinicia
restart: unless-stopped # Excepto si fue detenido
restart: on-failure # Solo si falla
restart: on-failure:3 # Max 3 intentos
restart: no # No reiniciarConceptos Clave
- Declarativo: Define estado deseado, no comandos
- Reproducible: Mismo compose.yaml = mismo resultado
- Servicios: Contenedores nombrados que se comunican
- Redes: Automáticas, DNS entre servicios
- Volúmenes: Persistencia declarada
- Dependencias: Orden de inicio (
depends_on) - Variables: Configuración externa (.env)
- Ciclo de vida: up, ps, logs, exec, down
Flujo Típico
# Desarrollo
docker compose up -d
docker compose logs -f api
# Editar código
# Cambios automáticos (si bind mount)
# Testing
docker compose exec api npm test
# Producción
docker compose down -v
docker compose up -d --build
# Limpieza
docker compose down -vRelaciones
Conecta con
- Docker Compose — Package manager de multi-contenedores
- Docker — Plataforma base
- Creación de Imágenes en Docker — Define imágenes que Compose orquesta
- Almacenamiento en Docker — Define volúmenes
- Redes en Docker — Define redes
Parte de
- Orquestación de múltiples contenedores
- Infrastructure as Code declarativo