Docker Compose Guide
Docker Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application's services, networks, and volumes.
💡 Tip: Docker Compose simplifies managing complex applications with multiple containers that need to work together.
Why Use Docker Compose?
- 📝 Define all services in a single file
- 🔄 Start/stop all services with one command
- 🌐 Automatic networking between containers
- 💾 Manage volumes and persistent data
- 🔧 Easy environment variable configuration
Installation
Standalone Compose V2
# Linux
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify installation
docker-compose --version
Docker Desktop
Docker Compose is included in Docker Desktop for Windows and macOS.
Basic docker-compose.yml
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html
environment:
- NGINX_HOST=localhost
networks:
- mynetwork
networks:
mynetwork:
driver: bridge
Common Service Configuration
Image
services:
web:
image: nginx:latest # Use existing image
# OR
build: . # Build from Dockerfile
# OR
build:
context: ./app
dockerfile: Dockerfile.dev
Ports
services:
web:
ports:
- "8080:80" # host:container
- "443:443"
- "3000:3000"
expose:
- "8080" # Expose internally only
Volumes
services:
web:
volumes:
# Bind mount
- ./data:/var/lib/data
# Named volume
- db-data:/var/lib/db
# Anonymous volume
- /cache
volumes:
db-data:
driver: local
Environment Variables
services:
web:
environment:
- NODE_ENV=production
- DATABASE_URL=postgres://localhost/db
- DEBUG=false
# OR from file
env_file:
- .env
- .env.production
Networks
services:
web:
networks:
- frontend
- backend
db:
networks:
- backend
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # No external access
Dependencies
services:
web:
depends_on:
- db
- redis
db:
image: postgres:15
# web will wait for db to start
Complete Example
Full-stack application with frontend, backend, and database:
version: '3.8'
services:
# Frontend
frontend:
build: ./frontend
ports:
- "3000:3000"
volumes:
- ./frontend:/app
- /app/node_modules
environment:
- REACT_APP_API_URL=http://backend:5000
depends_on:
- backend
networks:
- app-network
# Backend API
backend:
build: ./backend
ports:
- "5000:5000"
volumes:
- ./backend:/app
- /app/node_modules
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://user:password@db:5432/mydb
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
networks:
- app-network
# Database
db:
image: postgres:15-alpine
ports:
- "5432:5432"
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
# Redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
postgres-data:
redis-data:
Health Checks
Define health checks to ensure services are running properly:
services:
web:
image: nginx:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
Common Commands
Starting Services
# Start all services
docker-compose up
# Start in detached mode
docker-compose up -d
# Start specific services
docker-compose up web db
# Build images before starting
docker-compose up --build
# Recreate containers
docker-compose up --force-recreate
Stopping Services
# Stop all services
docker-compose stop
# Stop and remove containers
docker-compose down
# Stop and remove containers, volumes, networks
docker-compose down -v
# Stop and remove all resources
docker-compose down --remove-orphans
Viewing Logs
# View all logs
docker-compose logs
# Follow logs in real-time
docker-compose logs -f
# View logs for specific service
docker-compose logs web
# Last 100 lines
docker-compose logs --tail=100
Managing Services
# List running services
docker-compose ps
# Execute command in running container
docker-compose exec web sh
# Run one-off command
docker-compose run web npm test
# Restart service
docker-compose restart web
# Scale service to multiple instances
docker-compose up --scale web=3
Environment Variables
Create a .env file in the same directory as docker-compose.yml:
# .env
POSTGRES_DB=mydb
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret123
DATABASE_URL=postgresql://admin:secret123@db:5432/mydb
Reference in docker-compose.yml:
services:
db:
environment:
- POSTGRES_DB=${POSTGRES_DB}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
Profiles
Use profiles to define service variants:
version: '3.8'
services:
web:
image: nginx:latest
profiles:
- production
web-dev:
image: nginx:latest
profiles:
- development
db:
image: postgres:15
Usage:
# Start with specific profile
docker-compose --profile production up
# Start all services
docker-compose up
Useful Patterns
Development with Hot Reload
services:
web:
build: .
volumes:
- ./src:/app/src # Mount source code
- /app/node_modules # Exclude node_modules
command: npm run dev # Development server
Override Configuration
Create docker-compose.override.yml (automatically loaded):
# docker-compose.override.yml
version: '3.8'
services:
web:
ports:
- "3000:3000"
volumes:
- ./src:/app/src
Multiple Compose Files
# Base configuration
docker-compose.yml
# Production configuration
docker-compose.prod.yml
# Use multiple files
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
Troubleshooting
Issue: Port Already in Use
Error:
Solution: Change port mapping or stop conflicting service
bind: address already in use
Solution: Change port mapping or stop conflicting service
Issue: Container Keeps Restarting
# Check logs
docker-compose logs service-name
# Check container status
docker-compose ps
# Inspect container
docker inspect $(docker-compose ps -q service-name)
Issue: Cannot Connect to Database
💡 Solutions:
- Ensure
depends_onis configured - Use service name as hostname (not localhost)
- Check network configuration
- Verify environment variables
Best Practices
✅ Do:
- Use version 3.8 or higher
- Define networks explicitly
- Use named volumes for persistence
- Set up health checks
- Use environment variables
- Keep services stateless when possible
- Document with comments
⚠️ Don't:
- Store secrets in plain text
- Use
:latesttag in production - Expose unnecessary ports
- Mount entire project directory in production
- Share credentials via environment files in Git
Next Steps
- Best Practices - Production-ready Docker practices
- Dockerfile Guide - Learn to create efficient Dockerfiles
- Kubernetes - Container orchestration