DevOps Lesson 5: Docker Compose
Docker Compose runs multi-container applications with one command. Instead of starting app + database + Redis separately, compose starts everything together.
docker-compose.yml
# docker-compose.yml
version: "3.9"
services:
# Node.js API
api:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
- REDIS_URL=redis://cache:6379
depends_on:
db:
condition: service_healthy
volumes:
- .:/app # mount local code (for development)
restart: unless-stopped
# PostgreSQL Database
db:
image: postgres:16
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data # persist data!
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 5s
# Redis Cache
cache:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data: # named volume (data persists across restarts!)
Compose Commands
docker compose up -d # start all services (detached)
docker compose down # stop and remove containers
docker compose logs -f api # tail api logs
docker compose exec api sh # shell into running api
docker compose restart api # restart one service
docker compose ps # status of all services
docker compose build # rebuild images
🏋️ Practice Task
Create a full docker-compose.yml for: API (your Node.js app), PostgreSQL with health check, Redis for sessions, Nginx as reverse proxy. Start everything with docker compose up -d. Verify all services are healthy with docker compose ps.
💡 Hint: Nginx config: proxy_pass http://api:3000; in the location / block. Add nginx service with volume mount to ./nginx.conf