Skip to content

Thực hành: Docker Compose Orchestration

🎯 Mục tiêu

🎯 Sau bài thực hành này, bạn sẽ:

  • Thiết kế docker-compose.yml cho ứng dụng multi-service
  • Cấu hình networks, volumes, và environment variables đúng cách
  • Phân biệt depends_on và healthcheck để quản lý startup order
  • Chọn networking strategy phù hợp cho microservices

Phần 1: Trắc nghiệm

🧠 Quiz

Câu 1: depends_on trong Docker Compose đảm bảo điều gì?

  • [ ] A) Service phụ thuộc chỉ start khi service kia healthy và sẵn sàng nhận request
  • [x] B) Service phụ thuộc chỉ start sau khi container của service kia đã được tạo
  • [ ] C) Tự động restart service nếu dependency bị crash
  • [ ] D) Chia sẻ network giữa hai service

💡 Giải thích: depends_on chỉ đảm bảo thứ tự khởi tạo container — KHÔNG đợi service thực sự ready. Dùng healthcheck với condition: service_healthy để đợi service sẵn sàng.

🧠 Quiz

Câu 2: Sự khác biệt giữa named volume và bind mount trong Compose?

  • [ ] A) Không có khác biệt — cả hai đều mount thư mục host vào container
  • [ ] B) Named volume nhanh hơn bind mount trên mọi hệ điều hành
  • [x] C) Named volume do Docker quản lý và persist data, bind mount map trực tiếp thư mục host
  • [ ] D) Bind mount chỉ hoạt động trên Linux, named volume hoạt động mọi nơi

💡 Giải thích: Named volume (db-data:/var/lib/postgresql/data) được Docker quản lý, persist độc lập với container. Bind mount (./src:/app/src) map trực tiếp thư mục host — phù hợp dev nhưng không nên cho production data.

🧠 Quiz

Câu 3: Khi hai service cùng Compose file, chúng giao tiếp với nhau qua gì?

  • [ ] A) Địa chỉ IP cố định được gán cho mỗi container
  • [ ] B) Localhost với port mapping
  • [x] C) Service name làm hostname trên default network của Compose
  • [ ] D) Phải cấu hình DNS server riêng

💡 Giải thích: Docker Compose tự tạo default network. Service api gọi http://db:5432 được vì Compose đăng ký DNS với service name. Không cần expose port ra host để giao tiếp nội bộ.

Phần 2: Sắp xếp Compose File

🧩 Parsons Problem

Bài 1: Compose cho Web App + Database

Sắp xếp các phần của docker-compose.yml đúng thứ tự logic:

  1. Khai báo services: ở top level
  2. Định nghĩa service db với image postgres:16-alpine
  3. Cấu hình environment variables cho database (user, password, db name)
  4. Mount named volume db-data vào /var/lib/postgresql/data
  5. Thêm healthcheck: pg_isready -U postgres
  6. Định nghĩa service api với build: ./api
  7. Set depends_on: db với condition: service_healthy
  8. Map port 3000:3000 cho service api
  9. Khai báo volumes: ở top level với db-data:

🧩 Parsons Problem

Bài 2: Networking cho 3 Service

Sắp xếp cấu hình networking:

  1. Khai báo networks: với frontendbackend
  2. Service nginx kết nối cả frontendbackend, map port 80:80
  3. Service api chỉ kết nối backend
  4. Service db chỉ kết nối backend, không expose port ra host

Phần 3: Kịch bản thực tế

🎯 Scenario Choice

Chọn Networking Strategy cho Microservices

Tình huống: Hệ thống e-commerce gồm: frontend (React/Nginx), api-gateway, user-service, order-service, postgres.

Yêu cầu: Database không được truy cập từ frontend. Chỉ api-gateway expose port ra ngoài.

Câu hỏi: Bạn sẽ tổ chức network như thế nào?

Xem giải pháp gợi ý

Tạo 2 custom networks:

  • public-netfrontend + api-gateway
  • private-netapi-gateway + user-service + order-service + postgres

Lý do:

  • api-gateway ở cả 2 network — bridge giữa frontend và backend
  • postgres chỉ ở private-net — frontend không thể truy cập trực tiếp
  • Chỉ expose port 80 trên api-gateway
yaml
networks:
  public-net:
  private-net:
services:
  frontend:
    networks: [public-net]
  api-gateway:
    networks: [public-net, private-net]
    ports: ["80:80"]
  user-service:
    networks: [private-net]
  order-service:
    networks: [private-net]
  postgres:
    networks: [private-net]

WARNING

Compose phù hợp cho development và single-host. Multi-host cần Kubernetes hoặc Docker Swarm.