Docker Compose is a tool that helps you define and run multiple containers simultaneously through a YAML file. Version v2 brings many improvements in performance and new features.
I. Installation and Preparation
1. Check Docker Compose Version
1
2
3
4
5
| # Check current version
docker compose version
# Expected output (v2.x.x)
Docker Compose version v2.24.5
|
2. Basic Project Structure
1
2
3
4
5
6
7
8
| my-app/
├── docker-compose.yml
├── .env
├── app/
│ ├── Dockerfile
│ └── src/
└── nginx/
└── nginx.conf
|
II. Docker Compose v2 Syntax
1. Basic docker-compose.yml File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| version: "3.8"
services:
web:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
volumes:
- .:/app
- /app/node_modules
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
volumes:
postgres_data:
|
2. Using .env File
1
2
3
4
5
6
7
| # .env file
NODE_ENV=development
DB_HOST=db
DB_PORT=5432
DB_NAME=myapp
DB_USER=user
DB_PASSWORD=password
|
1
2
3
4
5
6
7
| # docker-compose.yml
services:
web:
environment:
- NODE_ENV=${NODE_ENV}
- DB_HOST=${DB_HOST}
- DB_PORT=${DB_PORT}
|
III. Best Practices for Docker Compose v2
1. Network Management
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| version: "3.8"
services:
frontend:
build: ./frontend
networks:
- frontend-network
backend:
build: ./backend
networks:
- frontend-network
- backend-network
database:
image: postgres:15
networks:
- backend-network
networks:
frontend-network:
driver: bridge
backend-network:
driver: bridge
|
2. Health Checks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| services:
web:
build: .
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
|
3. Resource Limits
1
2
3
4
5
6
7
8
9
10
11
| services:
web:
build: .
deploy:
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
cpus: "0.25"
memory: 256M
|
IV. Common Docker Compose v2 Commands
1. Basic Commands
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Start services (detached mode)
docker compose up -d
# View logs
docker compose logs -f
# Stop services
docker compose down
# Rebuild and restart
docker compose up --build -d
# View service status
docker compose ps
|
2. Advanced Commands
1
2
3
4
5
6
7
8
9
10
11
| # Run a command inside a container
docker compose exec web bash
# Scale a service
docker compose up --scale web=3 -d
# View resource usage
docker compose top
# Validate compose file
docker compose config
|
V. Real-World Example: Web App with Database
1. Node.js + PostgreSQL + Redis
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| version: "3.8"
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://user:password@db:5432/myapp
- REDIS_URL=redis://redis:6379
volumes:
- .:/app
- /app/node_modules
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
restart: unless-stopped
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis_data:/data
restart: unless-stopped
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
restart: unless-stopped
volumes:
postgres_data:
redis_data:
|
2. nginx.conf File
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| events {
worker_connections 1024;
}
http {
upstream app {
server app:3000;
}
server {
listen 80;
location / {
proxy_pass http://app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
|
VI. Override and Multiple Environments
1. docker-compose.override.yml
1
2
3
4
5
6
7
8
9
| # docker-compose.override.yml (automatically loaded)
version: "3.8"
services:
app:
volumes:
- .:/app
environment:
- DEBUG=true
|
2. Environment-specific Files
1
2
3
4
5
| # Development
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d
# Production
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
|
1
2
3
4
5
6
7
8
9
10
11
12
| # docker-compose.prod.yml
version: "3.8"
services:
app:
restart: always
deploy:
resources:
limits:
memory: 1G
environment:
- NODE_ENV=production
|
Implementation Notes
- When applying to your project, keep these important points in mind:
- Always use
.env files for sensitive data - Implement health checks for critical services
- Use named volumes for persistent data
- Configure appropriate restart policies
- Best practices:
- Separate networks for security
- Use specific image tags instead of
latest - Implement a proper logging strategy
- Troubleshooting:
- Use
docker compose logs to debug - Check
docker compose config before deploying - Monitor resource usage with
docker compose top
🎯 Conclusion
Docker Compose v2 is a powerful tool that helps you manage multi-container applications with ease. With the best practices above, you can build and deploy applications professionally and efficiently! 🚀
Try experimenting with the examples above and gradually apply them to your real-world projects. 😊