Module 10: Docker Compose for
Multi-Container Applications
Docker & Containerization Workshop
Presented by: Choudhry Shehryar, MLOps Engineer
Learning Objectives
● Master Docker Compose for multi-container application orchestration
● Implement production-grade Compose configurations
● Apply best practices for complex application deployments
Docker Compose Overview
What is Docker Compose?
● Tool for defining and running multi-container applications
● Uses YAML files to configure application services
● Manages complete application lifecycle
● Simplifies container networking and dependencies
Key Benefits
● Declarative service definition
● Environment consistency
● Simplified container orchestration
● Development-to-production workflow
Compose vs. Swarm vs. Kubernetes
Docker Compose Kubernetes
● Single-host deployments ● Enterprise-grade
● Development and testing orchestration
● Simple application stacks ● Advanced scheduling
● Simplicity and ease of use ● Self-healing
Docker Swarm deployments
● Extensive ecosystem
● Multi-host orchestration
● Built into Docker Engine
● Service-based deployments
● Simpler than Kubernetes
db:
Compose File Structure image: postgres:13
Basic Components
networks: # Network
version: '3.8' # Compose file version definitions
services: # Container definitions frontend:
web: backend:
image: nginx:latest volumes: # Volume
definitions
ports:
- "80:80" db-data:
Compose File Versions
Compose Docker Choosing a Version
Version Engine
● Use latest supported by
3.8 19.03.0+
your Docker Engine
3.7 18.06.0+ ● Consider feature
3.0 1.13.0+ requirements
● Address compatibility
2.4 17.12.0+ with deployment
2.0 1.10.0+ environment
1.0 1.9.1+
networks:
- frontend # Network
Service Configuration attachment
Basic Service Definition volumes:
- ./config:/app/config # Volume
services: mounting
webapp: depends_on: #
image: webapp:1.0 Dependencies
# Use existing image
build: ./webapp # Or build from source
- db
container_name: webapp # Specific container name
restart: always # Restart policy
ports:
- "8080:80" # Port mapping
environment: # Environment variables
- NODE_ENV=production
Building Services
Build Configuration Options
services:
webapp:
build:
context: ./webapp # Build context directory
dockerfile: Dockerfile.dev # Custom Dockerfile
args: # Build arguments
VERSION: 1.0
target: production # Multi-stage build target
cache_from: # Build cache sources
- webapp:builder
Container Configuration
# Health check
Advanced Container Options healthcheck:
services: test: ["CMD", "curl", "-f",
webapp: "http://localhost/health"]
# Resource limits interval: 30s
deploy: timeout: 10s
resources: retries: 3
limits: # Logging
cpus: '0.5' logging:
memory: 512M driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Environment Variables # Variable substitution
environment:
Multiple Ways to Define Environment Variables - SERVICE_NAME=$
services: {SERVICE_NAME:-webapp}
webapp:
# Individual variables
environment:
- DEBUG=true
-
DATABASE_URL=postgres://postgres:password@db:5432/my
db
# From file
env_file:
- ./common.env
- ./app.env
Networking Configuration
# Network definitions
networks:
Network Types and Configuration
frontend:
services:
driver: bridge
webapp:
driver_opts:
networks:
com.docker.network.bridge.name:
frontend: frontend_bridge
ipv4_address: 172.16.238.10 ipam:
backend: driver: default
db: config:
networks: - subnet: 172.16.238.0/24
- backend backend:
# Volume definitions
Volume Management volumes:
app-data:
Volume Types and Configuration driver: local
# Service volumes driver_opts:
services: type: nfs
webapp: o: addr=10.0.0.10,rw
volumes: device: ":/path/to/data"
- app-data:/app/data #
Named volume db-data:
- ./local/path:/app/config # Bind external: true # Use pre-existing
mount volume
- /tmp/cache #
Anonymous volume
db:
Secret Management
# Secret definitions
Working with Secrets secrets:
services: api_key:
webapp: file: ./secrets/api_key.txt
secrets: cert_key:
- source: api_key external: true # Use pre-
existing secret
target: /app/secrets/api_key
uid: '0'
gid: '0'
mode: 0400
# Check logs
Compose Commands
docker compose logs -f webapp
Lifecycle Management
# Execute command in container
# Start services
docker compose exec webapp sh
docker compose up -d
# Scale services
# Stop services
docker compose up -d --scale
docker compose down webapp=3
# View running services
docker compose ps
Compose Profiles
Using Profiles for Service Groups
Starting with Profiles
services:
docker compose --profile dev up -d
webapp:
image: my-webapp docker compose --profile monitoring up -d
profiles: ["prod", "dev"]
db:
image: postgres
profiles: ["prod", "dev"]
adminer:
image: adminer
profiles: ["dev"]
monitoring:
image: prometheus
profiles: ["monitoring"]
Extend & Override Configurations
Base Configuration Development Override Production Override
# docker-compose.yml # docker- # docker-
(base) compose.override.yml compose.prod.yml
services: services: services:
webapp: webapp: webapp:
image: build: ./webapp restart: always
webapp:latest volumes: deploy:
ports: - ./webapp:/app replicas: 3
- "80:80" environment:
- DEBUG=true
Environment-Specific Configurations
.env File
Using Multiple Compose Files # .env file
COMPOSE_PROJECT_NAME=myapp
# Development environment
POSTGRES_VERSION=13
docker compose up -d
# Production environment WEB_PORT=8080
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Staging with custom .env
docker compose --env-file .env.staging up -d
Health Checks & Dependencies
Dependencies
Health Checks services:
services: webapp:
webapp: depends_on:
healthcheck: db:
test: ["CMD", "curl", "-f", condition: service_healthy
"http://localhost/health"]
redis:
interval: 30s
condition: service_started
timeout: 10s
db:
retries: 3
image: postgres
start_period: 15s
Compose Best Practices
Configuration Best Practices
● Use .env files for environment-specific values
● Keep secrets out of Compose files
● Create separate override files per environment
● Document configuration options
● Use version control for Compose files
● Implement health checks for critical services
● Set appropriate restart policies
● Define resource constraints for production
Hands-On Exercises
Exercise 1: Basic Compose Setup Exercise 3: Production
Configuration
● Create a Compose file for web + database
● Configure networking and volumes ● Create production overrides
● Test service dependencies ● Implement security best
practices
Exercise 2: Document Analysis System
● Configure monitoring and
● Implement the full system Compose file logging
● Configure development overrides
● Test the multi-container application
Questions & Next Steps
● Specific application needs?
● Custom configuration requirements?
● Integration challenges?