1. Docker Compose là gì?
Docker Compose là tool cho phép định nghĩa và chạy multi-container applications bằng một file YAML duy nhất. Thay vì chạy nhiều lệnh docker run, bạn chỉ cần docker compose up.
Tại sao cần Docker Compose?
Ứng dụng thực tế có nhiều services: web, database, cache, queue, ...
Quản lý dependencies giữa các services
Reproducible environments cho development và testing
Infrastructure as Code - mọi thứ trong version control
2. Cú pháp docker-compose.yml
2.1. Cấu trúc cơ bản
# docker-compose.yml services: web: image: nginx:1.27-alpine ports: - "80:80" volumes: - ./html:/usr/share/nginx/html:ro depends_on: - apiapi: build: ./backend ports: - "3000:3000" environment: - NODE_ENV=development - DB_HOST=db depends_on: db: condition: service_healthy
db: image: postgres:16-alpine environment: POSTGRES_DB: myapp POSTGRES_USER: admin POSTGRES_PASSWORD: secretpassword volumes: - db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U admin -d myapp"] interval: 10s timeout: 5s retries: 5
volumes: db-data:
networks: default: driver: bridge
2.2. Services
services: # Sử dụng image có sẵn redis: image: redis:7-alpine ports: - "6379:6379"Build từ Dockerfile
app: build: context: . dockerfile: Dockerfile args: NODE_ENV: production image: myapp:latest # Tag cho built image
2.3. Ports
services:
web:
ports:
- "80:80" # host:container
- "443:443"
- "3000:3000"
- "127.0.0.1:8080:80" # Bind chỉ localhost
2.4. Volumes
services: db: volumes: - db-data:/var/lib/postgresql/data # Named volume - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # Bind mount - /tmp/logs:/var/log # Host path
volumes: db-data: driver: local
2.5. Environment Variables
services: app: # Inline environment: - NODE_ENV=production - DB_HOST=db - DB_PORT=5432# Hoặc dùng map syntax environment: NODE_ENV: production DB_HOST: db # Từ .env file env_file: - .env - .env.local
2.6. depends_on và Healthcheck
services: app: depends_on: db: condition: service_healthy # Đợi db healthy redis: condition: service_started # Đợi redis bắt đầudb: image: postgres:16-alpine healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 start_period: 30s
redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 3
2.7. Networks
services: frontend: networks: - frontend-netapi: networks: - frontend-net - backend-net
db: networks: - backend-net
networks: frontend-net: backend-net:
3. Docker Compose CLI
# Khởi động tất cả services docker compose upKhởi động ở background
docker compose up -d
Build và khởi động
docker compose up -d --build
Dừng tất cả services
docker compose down
Dừng và xóa volumes
docker compose down -v
Xem trạng thái services
docker compose ps
Xem logs
docker compose logs docker compose logs -f api # Follow logs của service cụ thể
Exec vào service
docker compose exec api sh docker compose exec db psql -U admin -d myapp
Run one-off command
docker compose run --rm api npm test
Scale service
docker compose up -d --scale api=3
Restart service
docker compose restart api
Build/rebuild images
docker compose build docker compose build --no-cache api
4. Lab: Deploy Full-stack Application
Triển khai ứng dụng với Nginx + Node.js API + PostgreSQL + Redis:
# docker-compose.yml
services:
# Nginx Reverse Proxy
nginx:
image: nginx:1.27-alpine
ports:
- "80:80"
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
api:
condition: service_healthy
restart: unless-stopped
# Node.js API
api:
build:
context: ./backend
dockerfile: Dockerfile
environment:
NODE_ENV: production
DB_HOST: db
DB_PORT: 5432
DB_NAME: myapp
DB_USER: admin
DB_PASSWORD: secretpassword
REDIS_URL: redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/health"]
interval: 15s
timeout: 5s
retries: 3
restart: unless-stopped
# PostgreSQL Database
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: admin
POSTGRES_PASSWORD: secretpassword
volumes:
- postgres-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin -d myapp"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
# Redis Cache
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 3
restart: unless-stopped
volumes:
postgres-data:
redis-data:
# Deploy
docker compose up -d
# Kiểm tra
docker compose ps
docker compose logs -f
# Test
curl http://localhost/api/health
5. Tổng kết
Trong bài này, bạn đã nắm được:
Docker Compose là gì và tại sao cần dùng
Cú pháp docker-compose.yml: services, volumes, networks
depends_on với healthcheck conditions
Docker Compose CLI: up, down, ps, logs, exec
Lab thực hành: Nginx + Node.js + PostgreSQL + Redis
Bài tiếp theo sẽ đi sâu vào Docker Networking - cách containers giao tiếp với nhau.