Click any item to expand the explanation and examples.
🚀 Commands
docker compose up / down / logs cli
# Start all services docker compose upStart in background
docker compose up -d
Rebuild images and start
docker compose up —build
Stop and remove containers
docker compose down
Stop and remove containers + volumes (deletes data!)
docker compose down -v
View logs
docker compose logs docker compose logs -f # Follow (stream) docker compose logs -f app # Specific service
Restart a service
docker compose restart app
Run a one-off command
docker compose exec app bash # Shell into running container docker compose run app npm test # Run command in new container
List running services
docker compose ps
Pull latest images
docker compose pull
📐 Service Configuration
Build from Dockerfile service
services:
app:
build: . # Dockerfile in current dir
build:
context: .
dockerfile: Dockerfile.dev
args:
NODE_ENV: development
ports:
- "3000:3000"
volumes:
- .:/app # Mount source code
- /app/node_modules # Don't override node_modules
environment:
- NODE_ENV=development
command: npm run dev # Override CMD
Use a pre-built image service
services:
db:
image: postgres:16
ports:
- "5432:5432"
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U myuser"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- “6379:6379”
depends_on and healthchecks service
services:
app:
build: .
depends_on:
db:
condition: service_healthy # Wait until healthy
redis:
condition: service_started # Just wait until started
db:
image: postgres:16
healthcheck:
test: [“CMD-SHELL”, “pg_isready”]
interval: 5s
retries: 5
Without condition: service_healthy, depends_on only waits for the container to start — not for the service inside to be ready.
📁 Volumes
Named volumes and bind mounts volume
services:
app:
volumes:
# Bind mount (host path : container path)
- ./src:/app/src
- ./config.json:/app/config.json:ro # Read-only
# Named volume (managed by Docker)
- node_modules:/app/node_modules
db:
volumes:
- db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql # Run on first start
Declare named volumes
volumes:
db_data:
node_modules:
Bind mounts = your files synced into the container. Named volumes = Docker-managed persistent storage.
🌐 Networks
Custom networks network
# Services on the same network can reach each other by service name
services:
app:
networks:
- frontend
- backend
api:
networks:
- backend
db:
networks:
- backend
networks:
frontend:
backend:
By default, all services in a compose file share one network. Custom networks let you isolate services (e.g., frontend can’t reach the database directly).
🔐 Environment Variables
env vars, .env files, secrets env
# Inline
services:
app:
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:pass@db:5432/myapp
From .env file
services:
app:
env_file:
- .env
- .env.local
Interpolation from host environment or .env
services:
app:
image: myapp:${TAG:-latest} # Default to “latest”
environment:
- API_KEY=${API_KEY} # From host or .env
Docker Compose automatically reads a .env file in the same directory as docker-compose.yml.
⚡ Common Stacks
Node.js + PostgreSQL + Redis recipe
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
volumes:
- .:/app
- /app/node_modules
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: [“CMD-SHELL”, “pg_isready”]
interval: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
db_data: