Docker Compose
Un archivo YAML que describe todos los contenedores de tu proyecto y cómo se conectan. Un solo comando lo levanta todo.
Qué pasa con docker compose up
Del YAML a contenedores, red y volumen.
El prefijo pruebas-docker_ sale del nombre de la carpeta (nombre del proyecto). Cambialo con -p <nombre> o con name: arriba del YAML.
Comandos de compose
Se ejecutan en la carpeta del docker-compose.yml.
Levantar y bajar
docker compose updocker compose up -ddocker compose up --builddocker compose downdocker compose down -vUsar otro archivo
docker compose -f docker-compose-dev.yml up-f va antes de up.docker compose -f docker-compose-dev.yml down-f.docker compose -f docker-compose.yml -f docker-compose.override.yml updocker compose configOperar servicios
docker compose psdocker compose logs -f chanchitodocker compose exec chanchito shdocker compose restart chanchitodocker compose stop
docker compose startdocker compose build chanchitodocker compose (con espacio) es la versión actual integrada en Docker. docker-compose (con guion) es la v1, ya discontinuada.
Claves del YAML
Lo que va dentro de cada servicio.
Referencia de claves
| Clave | Para qué | Ejemplo |
|---|---|---|
services | Los contenedores a crear (uno por clave) | services: chanchito: … |
build | Construir desde un Dockerfile. Forma corta = carpeta; forma larga = context + dockerfile | build: . |
image | Usar una imagen ya hecha (Docker Hub) | image: mongo:7 |
ports | Mapeo "HOST:CONTENEDOR" (entre comillas) | - "3000:3000" |
environment | Variables de entorno | - NODE_ENV=production |
env_file | Variables desde archivo | env_file: .env |
volumes | Volúmenes nombrados o bind mounts | - mongo-data:/data/db · - .:/home/app |
depends_on | Orden de arranque (este arranca después de…) | depends_on: [monguito] |
links | Legacy. Ya no hace falta: la red de compose resuelve por nombre | - monguito |
restart | Reinicio automático | restart: unless-stopped |
command | Pisa el CMD del Dockerfile | command: npm run dev |
container_name | Nombre fijo del contenedor | container_name: monguito |
networks | Redes personalizadas (opcional) | networks: [backend] |
volumes (raíz) | Declara los volúmenes nombrados | volumes: mongo-data: |
version: "3.9" al principio del archivo es obsoleto: Compose v2 lo ignora y muestra un warning. Podés borrarlo.
YAML usa espacios, nunca tabs. La indentación define la jerarquía; mantené siempre el mismo ancho (2 o 4 espacios).
Compose de producción
La imagen lleva el código adentro (Dockerfile con COPY).
docker-compose.yml
services:
# Contenedor de nuestra aplicación
chanchito:
build: . # busca el Dockerfile en la carpeta actual
ports:
- "3000:3000" # PC:3000 -> contenedor:3000
links:
- monguito # (legacy) chanchito habla con monguito
# Contenedor de MongoDB
monguito:
image: mongo # imagen oficial
ports:
- "27017:27017"
environment: # crea el usuario admin al iniciar
- MONGO_INITDB_ROOT_USERNAME=mati
- MONGO_INITDB_ROOT_PASSWORD=<password>
volumes:
- mongo-data:/data/db # persiste los datos
# mysql -> /var/lib/mysql
# postgres -> /var/lib/postgresql/data
# Declaración del volumen nombrado
volumes:
mongo-data:
Versión recomendada
services:
chanchito:
build: .
ports:
- "3000:3000"
depends_on:
- monguito # arranca después de mongo
environment:
- MONGO_URL=mongodb://${MONGO_USER}:${MONGO_PASSWORD}@monguito:27017/miapp?authSource=admin
restart: unless-stopped
monguito:
image: mongo:7 # versión fija
ports:
- "27017:27017" # opcional: solo si querés entrar con Compass
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
depends_onen vez delinks- Credenciales en .env, no en el YAML (no se suben a git)
- En
app.js:mongoose.connect(process.env.MONGO_URL)
Compose de desarrollo
Monta tu carpeta en el contenedor: editás y nodemon recarga, sin rebuild.
docker-compose-dev.yml
services:
chanchito:
build:
context: . # carpeta usada como contexto
dockerfile: Dockerfile.dev # Dockerfile a usar
ports:
- "3000:3000"
links:
- monguito
volumes:
- .:/home/app # reemplaza al COPY del Dockerfile
monguito:
image: mongo
ports:
- "27017:27017"
environment:
- MONGO_INITDB_ROOT_USERNAME=mati
- MONGO_INITDB_ROOT_PASSWORD=<password>
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
Cómo funciona el bind mount
Antes: COPY . /home/app (copia fija en la imagen). Ahora: .:/home/app (carpeta compartida en vivo).
Producción vs Desarrollo
Las diferencias entre tus dos archivos, en una tabla.
Comparativa
| Producción | Desarrollo | |
|---|---|---|
| Archivo compose | docker-compose.yml | docker-compose-dev.yml |
| Dockerfile | Dockerfile (build: .) | Dockerfile.dev (context + dockerfile) |
| Código | Copiado en la imagen con COPY | Montado con volumes: - .:/home/app |
| Arranque | node app.js | nodemon -L app.js (recarga automática) |
| Al cambiar código | docker compose up --build | Nada: guardás y listo |
| Levantar | docker compose up | docker compose -f docker-compose-dev.yml up |
Variables y archivo .env
Saca contraseñas del YAML. Compose lee automáticamente el .env de la misma carpeta.
1. Crear .env
MONGO_USER=mati
MONGO_PASSWORD=<password>
2. Usarlas en el compose
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_USER}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_PASSWORD}
# o pasar el archivo entero al contenedor:
env_file: .env
3. Verificar
docker compose configMONGO_INITDB_ROOT_* solo se aplica la primera vez (con el volumen vacío). Si cambiás la contraseña después, hacé down -v o cambiala dentro de Mongo.
Varios servicios: db · migrator · backend · frontend
El patrón de tu proyecto ASP.NET Core: el compose orquesta, cada Dockerfile solo construye.
Esqueleto
services:
db:
image: postgres:16
environment:
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
retries: 10
migrator:
build:
context: ./aspnet-core # TODA la solución
dockerfile: src/<Proyecto>.DbMigrator/Dockerfile
depends_on:
db:
condition: service_healthy # espera a que la DB esté lista
backend:
build:
context: ./aspnet-core
dockerfile: src/<Proyecto>.HttpApi.Host/Dockerfile
ports:
- "44300:8080" # PC:44300 -> contenedor:8080
environment:
- ConnectionStrings__Default=Host=db;Database=app;Username=postgres;Password=${DB_PASSWORD}
depends_on:
migrator:
condition: service_completed_successfully
frontend:
build: ./angular
ports:
- "4200:80"
depends_on:
- backend
volumes:
pg-data:
Claves de este patrón
context= qué carpeta ve el Dockerfile. Si el proyecto depende de otros (Domain, Application…), el context tiene que ser la raíz de la solución.dockerfile= ruta al Dockerfile relativa al context.depends_onsolo ordena el arranque. Para esperar a que algo esté listo usácondition: service_healthy+healthcheck.service_completed_successfully: el backend arranca recién cuando el migrator terminó bien.- En .NET,
__(doble guion bajo) en una variable =:enappsettings.json(ConnectionStrings:Default). - El host de la DB en el connection string es el nombre del servicio (
Host=db).
Regla de oro: el Dockerfile no sabe de puertos externos, variables ni de otros contenedores. Todo eso vive en el compose.