Sổ tay kỹ thuật

Docker Compose – pattern hay dùng

how-to#docker#docker-compose· cập nhật 2026-11-06

Dùng khi viết compose.yaml cho stack nhiều service cần healthcheck, thứ tự khởi động, profiles, biến môi trường và override theo môi trường.

Sửa trang này
Mục lục

Tóm tắt: Viết compose.yaml theo Compose Specification (không còn trường version:), dùng healthcheck + depends_on.condition: service_healthy để chờ DB sẵn sàng, profiles cho service phụ, .env cho biến, và compose.override.yaml cho cấu hình dev. Chạy bằng docker compose (plugin v2).

Luồng hoạt động

flowchart LR A[compose.yaml] --> M[Merge] B[compose.override.yaml] --> M E[".env"] -->|interpolation| M M --> C["docker compose up"] C --> D[(db)] D -->|service_healthy| W[api] W -->|service_started| P[proxy]

Cấu hình

Stack cơ bản

compose.yaml
name: netapp
 
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: app
      POSTGRES_DB: app
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets: [db_password]
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U app -d app"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s
    restart: unless-stopped
 
  api:
    image: registry.example.com/netapp-api:${API_TAG:-latest}
    env_file: .env
    environment:
      DATABASE_HOST: db
    depends_on:
      db:
        condition: service_healthy
        restart: true
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8000/healthz"]
      interval: 15s
      retries: 3
    restart: unless-stopped
 
  proxy:
    image: nginx:1.27
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      api:
        condition: service_started
 
  adminer:
    image: adminer
    profiles: [debug]
    ports:
      - "127.0.0.1:8081:8080"
 
volumes:
  pgdata:
 
secrets:
  db_password:
    file: ./secrets/db_password.txt

Điểm cần nhớ:

  • condition nhận service_started, service_healthy, service_completed_successfully (cho job migrate chạy một lần rồi thoát).
  • restart: true trong depends_on (Compose ≥ 2.17): khi db bị restart bởi lệnh Compose, api restart theo.
  • healthcheck.test dạng CMD cần binary có trong image (curl không có sẵn trong nhiều image slim/distroless).
  • Service có profiles chỉ chạy khi bật profile: docker compose --profile debug up -d.

Biến môi trường

.env
API_TAG=1.4.2
LOG_LEVEL=info
  • .env cạnh compose.yaml dùng cho interpolation ${VAR} trong file compose. Muốn biến vào container phải khai báo qua environment: hoặc env_file:.
  • Cú pháp: ${VAR:-default} (mặc định nếu rỗng/không đặt), ${VAR:?thông báo lỗi} (bắt buộc phải có).
  • Biến shell lúc chạy lệnh ưu tiên hơn .env.

Override theo môi trường

compose.override.yaml
services:
  api:
    build: ./api
    volumes:
      - ./api:/app
    environment:
      LOG_LEVEL: debug
    ports:
      - "127.0.0.1:8000:8000"

docker compose up tự đọc compose.yaml + compose.override.yaml. Production thì chỉ định file rõ ràng:

docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose -f compose.yaml -f compose.prod.yaml config   # xem kết quả merge

Có thể tái dùng khối cấu hình bằng include: (Compose ≥ 2.20) hoặc extension field + YAML anchor:

x-logging: &default-logging
  driver: json-file
  options: { max-size: "10m", max-file: "3" }
 
services:
  api:
    logging: *default-logging

Lệnh

Mục đích Lệnh
Kiểm tra cú pháp, xem file sau merge docker compose config
Khởi động / chờ tới khi healthy docker compose up -d / docker compose up -d --wait
Build lại rồi chạy docker compose up -d --build
Trạng thái (cột STATUS có health) docker compose ps
Log một service docker compose logs -f --tail 100 api
Chạy lệnh trong service docker compose exec api sh
Chạy job một lần docker compose run --rm api python manage.py migrate
Cập nhật image docker compose pull && docker compose up -d
Tạo lại một service docker compose up -d --force-recreate api
Dừng, xoá container + network docker compose down
Xoá luôn volume (mất dữ liệu) docker compose down -v

Lỗi thường gặp

Triệu chứng Nguyên nhân Cách xử lý
Cảnh báo the attribute version is obsolete File còn version: "3.8" Xoá dòng version:
docker-compose: command not found Máy chỉ có plugin v2 Dùng docker compose (cài gói docker-compose-plugin)
dependency failed to start: container db is unhealthy Healthcheck sai lệnh hoặc start_period quá ngắn docker inspect -f '{{json .State.Health}}' <c> xem output test
api lỗi kết nối DB dù có depends_on Dùng dạng list depends_on: [db], chỉ chờ container start Đổi sang condition: service_healthy
Biến ${VAR} rỗng, cảnh báo variable is not set .env không nằm cạnh file compose hoặc dùng --project-directory khác docker compose config để kiểm tra, hoặc --env-file
Biến có trong .env nhưng app không thấy .env chỉ dùng cho interpolation Thêm env_file: .env hoặc environment:
Đổi compose.yaml mà container không đổi Chưa up -d lại; với image tag cố định cần pull docker compose up -d (Compose tự recreate khi config đổi)
Port conflict address already in use Host đã có process dùng port ss -ltnp | grep :80

Tham khảo