Docker Compose
Define and run multi-container applications with Docker Compose. Services, networks, volumes, and environment configuration.
What Is Docker Compose?
Docker Compose lets you define a multi-container application in a single docker-compose.yml file and manage it with one command. Instead of running multiple docker run commands with flags, you declare all services, their configuration, networks, and volumes in one place.
docker-compose.yml Structure
services: # containers to run
web:
image: nginx
ports:
- "8080:80"
api:
build: ./api # build from a local Dockerfile
environment:
- NODE_ENV=production
depends_on:
- db
db:
image: postgres:15
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: secret
volumes: # named volumes
pgdata:
networks: # custom networks (optional — Compose creates a default)
backend:
Core Commands
# Start all services (build if needed), detached
docker compose up -d
# Start and force rebuild images
docker compose up -d --build
# Stop and remove containers (keeps volumes)
docker compose down
# Stop and remove containers AND volumes
docker compose down -v
# View logs for all services
docker compose logs -f
# View logs for one service
docker compose logs -f api
# List running services
docker compose ps
# Scale a service to N replicas
docker compose up -d --scale worker=3
Full Example: Node API + PostgreSQL + Redis
# docker-compose.yml
services:
api:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgresql://postgres:secret@db:5432/myapp
REDIS_URL: redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
volumes:
- ./src:/app/src # live reload in development
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
cache:
image: redis:7-alpine
volumes:
- redisdata:/data
volumes:
pgdata:
redisdata:
Environment Variables
Inline in docker-compose.yml
environment:
- NODE_ENV=production
- PORT=3000
From a .env file (default)
Compose automatically loads .env in the same directory:
# .env
DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
NODE_ENV=development
environment:
- DATABASE_URL=${DATABASE_URL}
- NODE_ENV=${NODE_ENV}
Multiple env files
docker compose --env-file .env.staging up -d
Service Dependencies and Health Checks
services:
api:
depends_on:
db:
condition: service_healthy # wait until healthy
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
Without condition: service_healthy, depends_on only waits for the container to start — not for the service inside it to be ready.
Running Commands
# Run a command in a running service
docker compose exec api node --version
# Run a one-off command in a new container
docker compose run --rm api npm run migrate
# Open a shell
docker compose exec db psql -U postgres
Overriding with Multiple Files
# docker-compose.yml — base config (shared)
# docker-compose.override.yml — dev overrides (applied automatically)
# docker-compose.prod.yml — production overrides
# Development (uses base + override automatically)
docker compose up -d
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
docker-compose.override.yml is merged automatically in development. Keep dev-only settings (bind mounts, debug ports, hot reload) there.
Frequently Asked Questions
What version of Docker Compose should I use?
Use the Compose V2 plugin (docker compose, not docker-compose). It ships with Docker Desktop and Docker Engine 23+. The standalone docker-compose binary is deprecated.
Do I need to define networks in docker-compose.yml?
No. Compose creates a default network automatically and all services join it. Define custom networks only when you need isolation between groups of services.
How do I run a one-off command against a service?
Use docker compose run --rm service-name command. This starts a fresh container for the service and removes it on exit.