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
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ớ:
conditionnhậnservice_started,service_healthy,service_completed_successfully(cho job migrate chạy một lần rồi thoát).restart: truetrongdepends_on(Compose ≥ 2.17): khidbbị restart bởi lệnh Compose,apirestart theo.healthcheck.testdạngCMDcần binary có trong image (curlkhông có sẵn trong nhiều image slim/distroless).- Service có
profileschỉ chạy khi bật profile:docker compose --profile debug up -d.
Biến môi trường
API_TAG=1.4.2
LOG_LEVEL=info.envcạnhcompose.yamldùng cho interpolation${VAR}trong file compose. Muốn biến vào container phải khai báo quaenvironment:hoặcenv_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
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ả mergeCó 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-loggingLệ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 |