| name | docker-compose |
| description | Define and run multi-container Docker applications using Docker Compose. Create compose files, manage service dependencies, configure networks and volumes, and orchestrate local development environments. Use when setting up multi-service applications or development environments. |
| license | MIT |
| metadata | {"author":"devops-skills","version":"1.0"} |
Docker Compose
Orchestrate multi-container applications with declarative YAML configuration.
When to Use This Skill
Use this skill when:
- Running multi-container applications locally
- Setting up development environments
- Defining service dependencies and networking
- Managing application stacks with multiple services
- Creating reproducible development setups
Prerequisites
- Docker Engine with Compose plugin (v2)
- Basic Docker knowledge
- YAML syntax understanding
Basic Configuration
Simple Application Stack
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgres://postgres:secret@db:5432/myapp
depends_on:
- db
- redis
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres-data:
Service Configuration
Build Options
services:
app:
build:
context: ./app
dockerfile: Dockerfile.dev
args:
NODE_VERSION: "20"
target: development
cache_from:
- myapp:cache
image: myapp:dev
Environment Variables
services:
app:
environment:
- NODE_ENV=production
- API_KEY=${API_KEY}
env_file:
- .env
- .env.local
Port Mapping
services:
web:
ports:
- "3000:3000"
- "127.0.0.1:9229:9229"
- "8080-8090:8080-8090"
expose:
- "3000"
Volume Mounts
services:
app:
volumes:
- app-data:/app/data
- ./src:/app/src
- ./config:/app/config:ro
- /app/node_modules
volumes:
app-data:
driver: local
Dependencies
services:
web:
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Networking
Custom Networks
services:
frontend:
networks:
- frontend-net
backend:
networks:
- frontend-net
- backend-net
db:
networks:
- backend-net
networks:
frontend-net:
driver: bridge
backend-net:
driver: bridge
internal: true
Network Aliases
services:
db:
networks:
backend:
aliases:
- database
- postgres
networks:
backend:
Resource Limits
services:
app:
deploy:
resources:
limits:
cpus: '2'
memory: 1G
reservations:
cpus: '0.5'
memory: 256M
Multiple Compose Files
Override Files
services:
web:
image: myapp:latest
ports:
- "3000:3000"
services:
web:
build: .
volumes:
- ./src:/app/src
environment:
- DEBUG=true
services:
web:
deploy:
replicas: 3
environment:
- DEBUG=false
Using Multiple Files
docker compose up
docker compose -f docker-compose.yml -f docker-compose.prod.yml up
docker compose -f docker-compose.yml -f docker-compose.prod.yml config
Profiles
services:
web:
image: myapp
db:
image: postgres:15
debug:
image: busybox
profiles:
- debug
monitoring:
image: prometheus
profiles:
- monitoring
docker compose up
docker compose --profile debug up
docker compose --profile debug --profile monitoring up
Commands
Lifecycle
docker compose up -d
docker compose up -d web
docker compose stop
docker compose down
docker compose down -v --rmi all
docker compose restart web
Building
docker compose build
docker compose build --no-cache
docker compose up --build
docker compose pull
Monitoring
docker compose logs -f
docker compose logs -f web
docker compose ps
docker compose top
Execution
docker compose run --rm web npm test
docker compose exec web /bin/sh
docker compose up -d --scale worker=3
Development Workflow
Watch Mode (Compose v2.22+)
services:
web:
build: .
develop:
watch:
- action: sync
path: ./src
target: /app/src
- action: rebuild
path: ./package.json
docker compose watch
Hot Reload Setup
services:
web:
build:
context: .
target: development
volumes:
- ./src:/app/src
- /app/node_modules
environment:
- CHOKIDAR_USEPOLLING=true
command: npm run dev
Common Patterns
Database Initialization
services:
db:
image: postgres:15
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d:ro
environment:
POSTGRES_DB: myapp
Reverse Proxy
services:
proxy:
image: traefik:v3.0
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/etc/traefik/traefik.yml:ro
web:
labels:
- "traefik.enable=true"
- "traefik.http.routers.web.rule=Host(`app.localhost`)"
Common Issues
Issue: Container Cannot Resolve Service Name
Problem: Service can't connect to another service by name
Solution: Ensure services are on the same network, check depends_on
Issue: Volume Permissions
Problem: Container can't write to mounted volume
Solution: Match container user UID with host, or use named volumes
Issue: Port Already in Use
Problem: Error binding to port
Solution: Change host port or stop conflicting service
Issue: Changes Not Reflected
Problem: Code changes don't appear in container
Solution: Check volume mounts, rebuild if Dockerfile changed
Best Practices
- Use named volumes for persistent data
- Define healthchecks for database dependencies
- Use profiles to separate optional services
- Keep secrets in .env files (not committed)
- Use override files for environment-specific config
- Pin image versions for reproducibility
- Use networks to isolate service groups
- Leverage watch mode for development
Related Skills