Docker Compose: Multi-Container Applications
Manage multiple containers with Docker Compose for local development.
By EMEPublished: February 20, 2025
dockerdocker-composecontainersorchestrationdevelopment
A Simple Analogy
Docker Compose is like a restaurant setup script. Instead of hiring employees one by one and explaining their roles, you give one script that sets up the kitchen, front desk, and delivery—all configured to work together automatically.
What Is Docker Compose?
Docker Compose is a tool for defining and running multi-container applications. It uses a YAML file to configure all services, networks, and volumes, then starts them with one command.
Why Use Docker Compose?
- Local development: Replicate production locally
- Simple startup: One command starts entire app
- Service linking: Containers communicate automatically
- Volume management: Persist data across runs
- Environment variables: Configure per service
Basic Structure
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://db:5432/myapp
depends_on:
- db
db:
image: postgres:15
environment:
- POSTGRES_DB=myapp
- POSTGRES_PASSWORD=secret
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Common Commands
# Start services
docker-compose up
# Start in background
docker-compose up -d
# View running services
docker-compose ps
# View logs
docker-compose logs -f web
# Stop services
docker-compose down
# Rebuild images
docker-compose build
Practical Example
version: '3.8'
services:
app:
build: .
container_name: myapp
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://postgres:password@db:5432/myapp
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
volumes:
- .:/app
- /app/node_modules
networks:
- app-network
db:
image: postgres:15
container_name: myapp_db
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- app-network
cache:
image: redis:7-alpine
container_name: myapp_cache
ports:
- "6379:6379"
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
db_data:
Usage:
docker-compose up -d
# App available at http://localhost:3000
Service Communication
services:
api:
environment:
- DB_HOST=postgres # Service name, not IP
- DB_PORT=5432
postgres:
# Services on same network can access via service name
In code:
const dbUrl = "postgresql://user:pass@postgres:5432/myapp";
// postgres is the service name from docker-compose.yml
Best Practices
- Use services names: Don't hardcode IPs
- Define networks: Control service communication
- Version control: Commit docker-compose.yml
- Environment files: Use .env for sensitive data
- Health checks: Ensure services are ready
Related Concepts to Explore
- Kubernetes (production orchestration)
- Docker networking
- Volume management and persistence
- Environment files and secrets
Summary
Docker Compose simplifies local development with multiple services. Define your entire stack once and start it reliably on any machine with one command.