Skip to content

Module 3: Orchestration with Docker Compose (Hợp tấu Container)

🎓 Instructor Profile

Kỹ sư Raizo (Phó CTO HPN) - Chuyên gia kiến trúc hệ thống, người tin rằng "Một container lẻ loi là một container buồn". Cùng Giáo sư Tom giải mã sự kỳ diệu của việc phối hợp dịch vụ.

Chào mừng các bạn đến với thế giới của Orchestration. Nếu Dockerfile là cách bạn tạo ra một "ngôi sao" (Container), thì Docker Compose chính là người nhạc trưởng (Conductor) điều khiển cả dàn nhạc giao hưởng.


🎻 Phần 1: From Solo to Symphony (Từ Đơn lẻ đến Hợp xướng)

Nỗi đau của Developer (The Pain Point)

Hãy tưởng tượng bạn đang phát triển một Web App hiện đại. Bạn cần bật:

  1. Frontend (React/Vue)
  2. Backend (Node/Go/Python)
  3. Database (PostgreSQL)
  4. Cache (Redis)
  5. Worker (Xử lý tác vụ nền)

Bạn phải mở 5 tab Terminal, gõ 5 lệnh docker run dài ngoằng nhớ nhớ quên quên. Sai một tham số là hệ thống "gãy".

Giải pháp: Infrastructure as Code (IaC)

docker-compose.yml ra đời. Nó là bản tuyên ngôn của hệ thống (Manifest). Chỉ với một file duy nhấtmột lệnh duy nhất, cả thế giới của bạn sẽ được dựng lên.

"Define and run multi-container Docker applications."


📐 Phần 2: The YAML Blueprint (Bản vẽ kỹ thuật)

Docker Compose sử dụng định dạng YAML (YAML Ain't Markup Language). Cấu trúc của nó rất trong sáng, dễ đọc.

💡 Compose V2 vs V1

Hiện tại, Docker đã chuyển sang Compose V2 (được viết lại bằng Go, tích hợp thẳng vào Docker CLI).

  • V1 (Cũ): docker-compose up (có gạch nối).
  • V2 (Mới): docker compose up (dùng dấu cách). PENALGO dạy chuẩn V2.

Cấu trúc giải phẫu

yaml
# Phiên bản schema (thường dùng 3.8 hoặc mới nhất)
version: "3.8"

services:
  # --- Dịch vụ 1: Web App ---
  web:
    build: .             # Build từ Dockerfile ở thư mục hiện tại
    ports:
      - "8000:5000"      # Mapping port Host:Container
    depends_on:
      - db               # Chỉ chạy sau khi 'db' khởi động

  # --- Dịch vụ 2: Database ---
  db:
    image: postgres:15-alpine
    volumes:
      - db_data:/var/lib/postgresql/data  # 📦 Persist data
    environment:
      POSTGRES_PASSWORD: ${DB_PASS}       # 🛡️ Dùng biến môi trường

volumes:
  db_data:               # Khai báo volume dùng chung

networks:
  app_network:           # 🔗 Kết nối mạng (Tuỳ chọn, Docker tự tạo default network)

🌐 Phần 3: Networking & Service Discovery (Ma thuật kết nối)

Tư duy Architect: Làm thế nào Frontend tìm thấy Backend, hay Backend tìm thấy Database khi IP của container thay đổi liên tục mỗi khi khởi động lại?

Docker Compose giải quyết bằng Internal DNS. Trong cùng một mạng Compose (default network), các dịch vụ gọi nhau bằng Service Name.

  • Để kết nối tới Database Postgres, Backend chỉ cần dùng host: db (Tên service khai báo trong YAML).
  • Connection String: postgres://user:pass@db:5432/dbname (Tuyệt đối không dùng IP như 172.18.0.2).

🔐 Phần 4: Environment & Secrets (Quản lý bí mật)

☠️ SECURITY ALERT

Tuyệt đối KHÔNG BAO GIỜ hardcode mật khẩu, API Key trực tiếp trong file docker-compose.yml và commit lên Git. Đây là lỗi sơ đẳng nhất khiến server bị hack.

Best Practice: Sử dụng .env

Docker Compose tự động đọc file .env đặt cùng thư mục.

  1. Tạo file .env:

    ini
    DB_USER=admin
    DB_PASS=SieuMatKhau123!@#
  2. Sử dụng trong YAML:

    yaml
    environment:
      - POSTGRES_USER=${DB_USER}
      - POSTGRES_PASSWORD=${DB_PASS}
  3. Thêm vào .gitignore:

    text
    .env

🚦 Phần 5: The Startup Order Problem (Vấn đề thứ tự khởi động)

Đây là kiến thức Deep Tech quan trọng.

Vấn đề: Bạn dùng depends_on: - db cho Web App. Docker đảm bảo container db được BẬT lên trước web. Nhưng: Docker không biết khi nào Database bên trong sẵn sàng nhận kết nối (Ready). Postgres có thể mất 10s để khởi động tiến trình. Web App chạy lên ngay -> Kết nối DB -> Lỗi "Connection Refused" -> Crash. 💥

Giải pháp: Healthchecks (Khám sức khỏe)

Sử dụng healthcheck kết hợp condition: service_healthy.

yaml
services:
  # Database có cơ chế tự khám bệnh
  db:
    image: postgres:15-alpine
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"] # Lệnh kiểm tra
      interval: 5s
      timeout: 5s
      retries: 5
  
  # Web App kiên nhẫn đợi bác sĩ bảo "Khỏe" mới chạy
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy  # 🟢 CHÌA KHÓA CỦA VẤN ĐỀ

🛠️ Phần 6: Essential Commands (Bộ công cụ chỉ huy)

LệnhTác dụngChú thích
docker compose up -dDựng toàn bộ stack và chạy ngầm (Detached).Lệnh dùng nhiều nhất.
docker compose downTắt và xóa containers, networks.Giữ lại Volumes (Dữ liệu an toàn).
docker compose down -vTắt và XÓA SẠCH cả Volumes.⚠️ Cẩn thận: Mất dữ liệu vĩnh viễn. Chỉ dùng khi muốn reset sạch sẽ.
docker compose logs -f [service]Xem log thời gian thực của dịch vụ cụ thể.VD: docker compose logs -f web
docker compose exec [service] [cmd]Chui vào container đang chạy để debug.VD: docker compose exec db psql -U admin

🏆 Challenge: The Resilient Stack

Nhiệm vụ: Viết file docker-compose.yml dựng hệ thống sau:

  1. Redis Service:
    • Image: redis:alpine
    • Có mật khẩu (Lấy từ biến môi trường ${REDIS_PASS}).
    • Có Healthcheck (Dùng lệnh redis-cli ping).
  2. Web Service:
    • Image: nginx:alpine
    • Port: 8080:80
    • Yêu cầu: Chỉ được phép khởi động SAU KHI Redis báo trạng thái "Healthy".

Gợi ý lệnh test sức khỏe Redis: redis-cli -a $REDIS_PASSWORD ping | grep PONG

Chúc các bạn thành công trong việc điều phối dàn nhạc container của mình! 🎼