Docker Compose
Docker Compose is a tool for defining and running multi-container Docker applications. Use a YAML file to configure your application's services, networks, and volumes.
Quick Reference
| Task | Command |
|---|---|
| Start services | docker-compose up -d |
| Stop services | docker-compose down |
| View logs | docker-compose logs -f |
| List services | docker-compose ps |
| Execute command | docker-compose exec <service> <command> |
| Build images | docker-compose build |
| Pull images | docker-compose pull |
| Restart services | docker-compose restart |
Installation
Linux
bash
# Download latest version
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# Make executable
sudo chmod +x /usr/local/bin/docker-compose
# Verify installation
docker-compose --versionmacOS and Windows
Docker Compose is included with Docker Desktop.
Basic Usage
Simple docker-compose.yml
yaml
version: "3.8"
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
db:
image: postgres:15
environment:
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:Start and Stop
bash
# Start all services (detached)
docker-compose up -d
# Start specific service
docker-compose up -d web
# Stop all services
docker-compose down
# Stop and remove volumes
docker-compose down -vCommon Commands
Starting Services
bash
# Start in foreground (see logs)
docker-compose up
# Start in background (detached)
docker-compose up -d
# Rebuild images before starting
docker-compose up --build
# Force recreate containers
docker-compose up --force-recreate
# Start specific services
docker-compose up -d web dbStopping Services
bash
# Stop services (keep containers)
docker-compose stop
# Stop and remove containers
docker-compose down
# Stop and remove containers, networks, and volumes
docker-compose down -v
# Stop and remove including images
docker-compose down --rmi allViewing Logs
bash
# View logs from all services
docker-compose logs
# Follow logs in real-time
docker-compose logs -f
# View logs from specific service
docker-compose logs -f web
# Show last N lines
docker-compose logs --tail=100
# Show timestamps
docker-compose logs -tExecuting Commands
bash
# Execute command in running service
docker-compose exec web bash
# Run one-off command (create new container)
docker-compose run --rm web bash
# Example from README (interactive mode)
docker-compose run --rm service1Managing Services
bash
# List running services
docker-compose ps
# List all services (including stopped)
docker-compose ps -a
# Restart services
docker-compose restart
# Restart specific service
docker-compose restart web
# Pause services
docker-compose pause
# Unpause services
docker-compose unpausedocker-compose.yml Examples
Interactive Service (from README)
yaml
version: "3"
services:
service1:
image: mcr.microsoft.com/dotnet/core/runtime:3.1
stdin_open: true
tty: true
command: "/bin/bash"bash
# Run interactively
docker-compose run --rm service1Web Application with Database
yaml
version: "3.8"
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://db:5432/myapp
depends_on:
- db
volumes:
- ./src:/app/src
restart: unless-stopped
db:
image: postgres:15
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:Development Stack
yaml
version: "3.8"
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- ./frontend/src:/app/src
- /app/node_modules
environment:
- REACT_APP_API_URL=http://localhost:8000
backend:
build:
context: ./backend
dockerfile: Dockerfile.dev
ports:
- "8000:8000"
volumes:
- ./backend:/app
environment:
- DEBUG=true
- DATABASE_URL=postgresql://postgres:password@db:5432/app
depends_on:
- db
- redis
db:
image: postgres:15
environment:
POSTGRES_DB: app
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:Microservices Architecture
yaml
version: "3.8"
services:
api-gateway:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- auth-service
- user-service
- order-service
auth-service:
build: ./services/auth
environment:
- SERVICE_NAME=auth
- JWT_SECRET=${JWT_SECRET}
networks:
- backend
user-service:
build: ./services/user
environment:
- SERVICE_NAME=user
- DB_HOST=postgres
depends_on:
- postgres
networks:
- backend
order-service:
build: ./services/order
environment:
- SERVICE_NAME=order
- DB_HOST=postgres
depends_on:
- postgres
- rabbitmq
networks:
- backend
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
networks:
- backend
rabbitmq:
image: rabbitmq:3-management
ports:
- "15672:15672"
networks:
- backend
networks:
backend:
volumes:
pgdata:Advanced Features
Environment Variables
Using .env file:
env
# .env
POSTGRES_PASSWORD=secret
API_KEY=abc123
NODE_ENV=productionyaml
# docker-compose.yml
version: "3.8"
services:
app:
image: myapp
environment:
- DB_PASSWORD=${POSTGRES_PASSWORD}
- API_KEY=${API_KEY}
- NODE_ENV=${NODE_ENV}Build Configuration
yaml
services:
app:
build:
context: .
dockerfile: Dockerfile.prod
args:
- BUILD_VERSION=1.0.0
- NODE_VERSION=20
cache_from:
- myapp:latest
target: productionHealth Checks
yaml
services:
app:
image: myapp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40sNetworks
yaml
version: "3.8"
services:
frontend:
image: frontend
networks:
- public
backend:
image: backend
networks:
- public
- private
database:
image: postgres
networks:
- private
networks:
public:
driver: bridge
private:
driver: bridge
internal: trueResource Limits
yaml
services:
app:
image: myapp
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
cpus: '1'
memory: 512MCommon Workflows
Development Workflow
bash
# Start development environment
docker-compose up -d
# View logs
docker-compose logs -f app
# Make code changes (automatically reflected if using volumes)
# Rebuild after dependency changes
docker-compose up -d --build
# Run tests
docker-compose exec app npm test
# Stop environment
docker-compose downProduction Deployment
bash
# Use production compose file
docker-compose -f docker-compose.prod.yml up -d
# View service status
docker-compose ps
# Scale services
docker-compose up -d --scale worker=3
# Update services
docker-compose pull
docker-compose up -d
# View logs
docker-compose logs -fDatabase Migrations
bash
# Run migrations
docker-compose exec app npm run migrate
# Create database backup
docker-compose exec db pg_dump -U user dbname > backup.sql
# Restore database
docker-compose exec -T db psql -U user dbname < backup.sqlMultiple Compose Files
Override Files
bash
# Base configuration
# docker-compose.yml (production defaults)
# Development overrides
# docker-compose.override.yml (automatically loaded)
# Start with defaults + overrides
docker-compose up -d
# Use specific file
docker-compose -f docker-compose.prod.yml up -d
# Combine multiple files
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -dExample Override
docker-compose.yml:
yaml
version: "3.8"
services:
app:
image: myapp:latest
environment:
- NODE_ENV=productiondocker-compose.override.yml:
yaml
version: "3.8"
services:
app:
build: .
volumes:
- ./src:/app/src
environment:
- NODE_ENV=development
ports:
- "9229:9229" # Debug portTroubleshooting
Services Won't Start
bash
# Check configuration syntax
docker-compose config
# View detailed logs
docker-compose logs
# Rebuild images
docker-compose build --no-cache
# Force recreate
docker-compose up -d --force-recreateNetwork Issues
bash
# List networks
docker network ls
# Inspect network
docker network inspect <network_name>
# Recreate networks
docker-compose down
docker-compose up -dVolume Issues
bash
# List volumes
docker volume ls
# Inspect volume
docker volume inspect <volume_name>
# Remove unused volumes
docker volume prune
# Remove all compose volumes
docker-compose down -vPerformance Issues
bash
# Check resource usage
docker stats
# Limit resources in compose file (see Resource Limits section)
# Check logs for errors
docker-compose logs --tail=100Best Practices
File Organization
- Use
.envfor environment-specific variables - Create separate compose files for different environments
- Use
docker-compose.override.ymlfor local development - Keep sensitive data out of compose files
Service Design
- One concern per service
- Use depends_on for service dependencies
- Implement health checks
- Use restart policies appropriately
Development
- Use volumes for code hot-reloading
- Expose debug ports in development
- Use override files for dev-specific config
- Don't commit
.envfiles with secrets
Production
- Use specific image tags (not
latest) - Set resource limits
- Implement logging and monitoring
- Use secrets management
- Regular backups of volumes
See Also
- Docker Containers - Container management
- Docker Images - Image management
- Docker Overview - Docker introduction