What is Docker Compose?
Docker Compose is a tool for defining and running multi-container applications.
Instead of manually running docker run commands with multiple flags, you describe
your entire application stack in a single docker-compose.yml (or compose.yml) file.
Basic Compose File
# docker-compose.yml
services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
Full Stack Example
# docker-compose.yml
services:
# PostgreSQL Database
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin"]
interval: 10s
timeout: 5s
retries: 5
# Redis Cache
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
# Backend API
api:
build:
context: ./api
dockerfile: Dockerfile
ports:
- "4000:4000"
environment:
DATABASE_URL: postgres://admin:secret@db:5432/myapp
REDIS_URL: redis://redis:6379
NODE_ENV: production
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
# Frontend App
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
NEXT_PUBLIC_API_URL: http://localhost:4000
depends_on:
- api
volumes:
postgres-data:
redis-data:
Compose Commands
# Start all services
docker compose up
# Start in detached mode (background)
docker compose up -d
# Build and start
docker compose up --build
# Stop all services
docker compose down
# Stop and remove volumes
docker compose down -v
# View service logs
docker compose logs
docker compose logs -f api # Follow specific service
# List running services
docker compose ps
# Restart a specific service
docker compose restart api
# Scale a service
docker compose up -d --scale api=3
# Execute a command in a service
docker compose exec api sh
docker compose exec db psql -U admin myapp
Development vs Production
# docker-compose.yml (base)
services:
api:
build: ./api
environment:
NODE_ENV: production
---
# docker-compose.override.yml (dev — auto-loaded)
services:
api:
build:
context: ./api
dockerfile: Dockerfile.dev
volumes:
- ./api/src:/app/src # Live reload
environment:
NODE_ENV: development
DEBUG: "true"
command: npm run dev
# Development (uses override automatically)
docker compose up
# Production (only base file)
docker compose -f docker-compose.yml up -d
# Or use multiple compose files
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
Environment Variables
# Using .env file (auto-loaded)
services:
api:
image: myapp:${APP_VERSION:-latest}
environment:
- DB_HOST=${DB_HOST}
- DB_PASSWORD=${DB_PASSWORD}
env_file:
- .env
- .env.local
Key Takeaways
- ✅ Docker Compose defines your entire stack in one file
- ✅ Use
depends_onwith health checks for reliable startup order - ✅ Use override files for dev-specific configuration
- ✅ Named volumes in the top-level
volumessection persist data