Docker Compose
This chapter will introduce Docker Compose in detail, teaching you how to use YAML files to define and manage multi-container applications, achieving container orchestration and service management.
Introduction to Docker Compose
What is Docker Compose?
Docker Compose is a tool for defining and running multi-container Docker applications. By using a YAML file to configure application services, you can then create and start all services with a single command.
Core Concepts
- Service: A component of the application, such as a web server, database, etc.
- Project: A complete application consisting of a set of related services
- Network: Network environment for service-to-service communication
- Volume: Storage for data persistence and sharing
Advantages of Docker Compose
- Simplify deployment: Start the entire application stack with one command
- Environment isolation: Each project has independent networks and namespaces
- Service discovery: Containers can communicate with each other by service name
- Configuration management: Unified management of all service configurations
- Scalability: Easily scale the number of service instances
Installing Docker Compose
Linux Installation
# Method 1: Download using curl
sudo curl -L "https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Method 2: Install using pip
pip3 install docker-compose
# Method 3: Use package manager (Ubuntu)
sudo apt-get update
sudo apt-get install docker-compose-plugin
# Verify installation
docker-compose --versionWindows and macOS
Docker Desktop already includes Docker Compose, no separate installation needed.
docker-compose.yml File Structure
Basic Structure
version: '3.8' # Compose file version
services: # Define services
web:
# Service configuration
db:
# Service configuration
volumes: # Define volumes (optional)
# Volume configuration
networks: # Define networks (optional)
# Network configurationVersion Compatibility
| Compose Version | Docker Engine Version |
|---|---|
| 3.8 | 19.03.0+ |
| 3.7 | 18.06.0+ |
| 3.6 | 18.02.0+ |
| 3.5 | 17.12.0+ |
Service Configuration Details
Basic Service Configuration
version: '3.8'
services:
web:
# Use existing image
image: nginx:latest
# Or build image
build: .
# build:
# context: .
# dockerfile: Dockerfile
# Container name
container_name: my-web-server
# Port mapping
ports:
- "8080:80"
- "8443:443"
# Environment variables
environment:
- NODE_ENV=production
- DEBUG=false
# Volume mounts
volumes:
- ./html:/usr/share/nginx/html
- logs:/var/log/nginx
# Networks
networks:
- frontend
# Dependencies
depends_on:
- db
# Restart policy
restart: unless-stoppedBuild Configuration
services:
web:
build:
context: . # Build context
dockerfile: Dockerfile.prod # Specify Dockerfile
args: # Build arguments
- VERSION=1.0
- BUILD_DATE=2023-01-01
target: production # Multi-stage build target
cache_from: # Cache source
- myapp:cache
image: myapp:latest # Image name after buildEnvironment Variable Configuration
services:
web:
# Method 1: Direct definition
environment:
- NODE_ENV=production
- PORT=3000
- DATABASE_URL=postgresql://user:pass@db:5432/mydb
# Method 2: Use object format
environment:
NODE_ENV: production
PORT: 3000
DATABASE_URL: postgresql://user:pass@db:5432/mydb
# Method 3: Read from file
env_file:
- .env
- .env.local
# Method 4: Inherit from host environment
environment:
- NODE_ENV
- DATABASE_URL=${DATABASE_URL}Volume Configuration
services:
web:
volumes:
# Bind mount
- ./src:/app/src
- ./config.json:/app/config.json:ro # Read-only
# Named volume
- app-data:/app/data
- logs:/var/log
# Anonymous volume
- /app/node_modules
# tmpfs mount
- type: tmpfs
target: /tmp
tmpfs:
size: 100M
# Define named volumes
volumes:
app-data:
driver: local
logs:
driver: local
driver_opts:
type: none
o: bind
device: /host/logsNetwork Configuration
services:
web:
networks:
- frontend
- backend
db:
networks:
- backend
# Define networks
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true # Internal network, cannot access externalDependencies and Startup Order
services:
web:
depends_on:
- db
- redis
# Or use conditional dependencies (requires healthcheck)
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:13
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
redis:
image: redis:alpineReal-World Application Examples
Example 1: Web Application + Database
version: '3.8'
services:
# Web application service
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
depends_on:
- db
volumes:
- ./uploads:/app/uploads
networks:
- app-network
restart: unless-stopped
# PostgreSQL database
db:
image: postgres:13
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- app-network
restart: unless-stopped
# Redis cache
redis:
image: redis:alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
networks:
- app-network
restart: unless-stopped
volumes:
postgres_data:
redis_data:
networks:
app-network:
driver: bridgeExample 2: Microservices Architecture
version: '3.8'
services:
# Nginx reverse proxy
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./ssl:/etc/nginx/ssl
depends_on:
- api
- web
networks:
- frontend
restart: unless-stopped
# Frontend application
web:
build:
context: ./frontend
dockerfile: Dockerfile
networks:
- frontend
restart: unless-stopped
# API service
api:
build:
context: ./backend
dockerfile: Dockerfile
environment:
- DATABASE_URL=postgresql://postgres:password@db:5432/api
- REDIS_URL=redis://redis:6379
depends_on:
- db
- redis
networks:
- frontend
- backend
restart: unless-stopped
# Database
db:
image: postgres:13
environment:
- POSTGRES_DB=api
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
volumes:
- db_data:/var/lib/postgresql/data
networks:
- backend
restart: unless-stopped
# Cache
redis:
image: redis:alpine
volumes:
- redis_data:/data
networks:
- backend
restart: unless-stopped
volumes:
db_data:
redis_data:
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: trueDocker Compose Commands
Basic Commands
# Start services
docker-compose up
# Start in background
docker-compose up -d
# Start specific services
docker-compose up web db
# Build images
docker-compose build
# Build and start
docker-compose up --build
# Stop services
docker-compose stop
# Stop and remove containers
docker-compose down
# Stop and remove containers, networks, volumes
docker-compose down -v
# View service status
docker-compose ps
# View logs
docker-compose logs
# View logs in real-time
docker-compose logs -f
# View specific service logs
docker-compose logs web
# Enter container
docker-compose exec web bash
# Run one-time command
docker-compose run web npm install
# Scale service instances
docker-compose up --scale web=3
# Restart service
docker-compose restart
# Pause service
docker-compose pause
# Resume service
docker-compose unpauseAdvanced Commands
# Validate configuration file
docker-compose config
# Display configuration (after variable resolution)
docker-compose config --services
# Pull images
docker-compose pull
# Push images
docker-compose push
# View port mapping
docker-compose port web 80
# View service processes
docker-compose top
# Send signal
docker-compose kill -s SIGINT web
# Remove stopped containers
docker-compose rm
# Force remove
docker-compose rm -fEnvironment Management
Multi-Environment Configuration
# Development environment
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
# Production environment
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
# Testing environment
docker-compose -f docker-compose.yml -f docker-compose.test.yml upConfiguration File Examples
docker-compose.yml (base configuration):
version: '3.8'
services:
web:
build: .
volumes:
- ./app:/app
networks:
- app-network
db:
image: postgres:13
networks:
- app-network
networks:
app-network:docker-compose.dev.yml (development environment override):
version: '3.8'
services:
web:
ports:
- "3000:3000"
environment:
- NODE_ENV=development
command: npm run dev
db:
ports:
- "5432:5432"
environment:
- POSTGRES_DB=devdb
- POSTGRES_USER=dev
- POSTGRES_PASSWORD=devpassdocker-compose.prod.yml (production environment override):
version: '3.8'
services:
web:
ports:
- "80:3000"
environment:
- NODE_ENV=production
restart: unless-stopped
db:
environment:
- POSTGRES_DB=proddb
- POSTGRES_USER=prod
- POSTGRES_PASSWORD=${DB_PASSWORD}
volumes:
- prod_db_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
prod_db_data:Health Checks and Dependency Management
Health Checks
version: '3.8'
services:
web:
image: nginx
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
db:
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 30s
timeout: 5s
retries: 5Chapter Summary
This chapter comprehensively introduced Docker Compose usage:
Key Points:
- Service orchestration: Use YAML files to define multi-container applications
- Network management: Service discovery and network isolation
- Data management: Volumes and persistent storage
- Environment management: Multi-environment configuration and variable management
- Scalability: Service scaling and load balancing
- Monitoring and debugging: Log management and troubleshooting
Best Practices:
- Use version control to manage Compose files
- Reasonably design service dependencies
- Use health checks to ensure service availability
- Separate configuration and code
- Regularly backup important data
In the next chapter, we will learn about Docker security best practices, including image security, container security, and network security.