Docker Compose: service graph và local environments
Compose khai báo một ứng dụng nhiều container bằng một application model chung. Nó giúp dựng môi trường dev/integration lặp lại được, nhưng thứ tự dependency không đồng nghĩa dependency đã thật sự sẵn sàng phục vụ request.
1. Compose
Một Compose application thường được mô tả trong compose.yaml. File này gom các service và các tài nguyên liên quan như network, volume, config và secret thành một project. Khi chạy docker compose up, Compose resolve model rồi tạo các resource/container cần thiết cho project đó.
2. Model
Mỗi service có thể định nghĩa image hoặc build, command, environment, port publishing, network, volume, healthcheck và resource-related configuration. Project name tạo namespace để nhiều stack tương tự có thể cùng tồn tại mà không trùng tên resource.
Trên cùng một Compose network, service name đóng vai trò tên DNS ổn định cho service discovery. Vì vậy container ứng dụng nên kết nối tới db:5432 hoặc redis:6379 thay vì hard-code IP container, vì IP có thể đổi sau recreate.
Ví dụ model tối thiểu
services:
api:
build: .
environment:
DB_HOST: db
depends_on:
db:
condition: service_healthy
networks: [backend]
db:
image: postgres:18
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
volumes:
- db-data:/var/lib/postgresql/data
networks: [backend]
networks:
backend:
volumes:
db-data:
Compose hỗ trợ merge nhiều file và profiles để tạo biến thể môi trường. Đây là công cụ hữu ích cho dev/test, nhưng nếu YAML có quá nhiều lớp override, anchor và profile, cấu hình thực tế trở nên khó review. Trước khi chạy, dùng docker compose config để render model cuối cùng mà Docker Compose sẽ áp dụng.
3. Startup
depends_on mô tả dependency graph và điều khiển thứ tự create/remove. Với short syntax, dependency chỉ cần được start trước; container đang chạy chưa chắc application bên trong đã ready. Long syntax cho phép condition: service_healthy hoặc service_completed_successfully.
Healthcheck phải đo readiness có ý nghĩa
Healthcheck nên kiểm tra đúng khả năng mà consumer cần: database chấp nhận connection/query tối thiểu, HTTP service trả lời endpoint readiness, hoặc broker nhận được protocol handshake. Tránh check giả kiểu echo ok hoặc chỉ kiểm tra process tồn tại nếu điều đó không chứng minh service phục vụ được traffic.
| Tình huống | Rủi ro | Thiết kế tốt hơn |
|---|---|---|
| App start ngay sau DB container | DB process còn recovery/migration nên connection fail | service_healthy + app retry/backoff |
| Dependency restart giữa runtime | Connection cũ chết, request fail | Reconnect, timeout, idempotency khi retry |
| Healthcheck quá nặng | Tạo tải hoặc tự làm service unhealthy | Probe rẻ, bounded timeout, đúng readiness contract |
| Healthcheck luôn xanh | False-ready che lỗi thật | Probe resource tối thiểu mà downstream thật sự cần |
4. Configuration
Interpolation và environment
.env chủ yếu là nguồn giá trị cho Compose interpolation; nó không phải secret store. Giá trị có thể đến từ shell, --env-file hoặc file .env và có precedence. Dùng biểu thức required như ${DB_HOST:?DB_HOST is required} để fail sớm thay vì chạy stack với giá trị rỗng ngoài ý muốn.
# .env
APP_PORT=8080
# compose.yaml
services:
api:
image: example/api:${API_TAG:-local}
ports:
- "${APP_PORT}:8080"
Có thể kiểm tra model đã resolve bằng docker compose config, và kiểm tra environment dùng cho interpolation bằng docker compose config --environment. Đừng đưa output này vào log công khai nếu có khả năng chứa giá trị nhạy cảm.
Secrets
Không commit password, token hay private key vào Compose file hoặc .env. Compose có top-level secrets; service chỉ nhận secret nếu được cấp rõ ràng và secret được mount vào container dưới dạng file. Với production, nguồn secret thực tế còn phụ thuộc platform và secret-management system của tổ chức.
services:
api:
image: example/api:1.4.2
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
Images, networks và volumes
- Image: tránh floating tag không kiểm soát. Dùng version tag rõ ràng; với supply-chain/reproducibility mạnh hơn có thể pin digest và quản lý quy trình update digest.
- Network: chỉ nối service vào network nó cần. Không publish DB/cache port ra host nếu chỉ service nội bộ cần truy cập.
- Named volume: data tồn tại qua container recreate và qua
docker compose down; nhưngdocker compose down -vxóa named volume của project, nên phải dùng có chủ đích. - Bind mount: phù hợp cho source code/config local nhưng phụ thuộc host path và permission; không nên mặc định coi nó tương đương storage production.
5. Use and limits
Compose rất phù hợp cho development, integration test, demo, CI job hoặc deployment single-host có failure model chấp nhận được. Nó giúp giữ parity ở application contract — cùng image, environment contract, ports, healthchecks và dependency topology — nhưng không tạo ra cùng infrastructure semantics với orchestrator nhiều node.
| Compose phù hợp | Cần thận trọng / cần platform khác |
|---|---|
| Developer chạy nhiều service local | High availability qua nhiều node/AZ |
| Integration test reproducible | Automatic rescheduling khi host chết |
| Demo, workshop, ephemeral stack | Progressive rollout, autoscaling, cluster policy phức tạp |
| Single-host internal workload | RPO/RTO yêu cầu orchestration/replication ngoài một host |
Failure window và recovery
Trên single-host Compose, host failure có thể làm toàn bộ stack mất cùng lúc. Restart policy có thể giúp container quay lại sau process/daemon restart, nhưng không thay thế multi-node failover. Với stateful service, phải xác định dữ liệu nằm ở đâu, backup/restore thế nào, và điều gì xảy ra nếu volume hoặc host bị mất.
Khi thay image/config, hãy render config trước, pull/build image trước nếu phù hợp, sau đó rollout trong maintenance window hoặc với reverse proxy/draining do hệ thống bên ngoài kiểm soát. Rollback phải chỉ rõ image/config version trước đó và migration database có backward-compatible hay không.
Capacity và operational signals
- CPU, memory, file descriptors và disk của host; OOM/restart count của container.
- Disk free/inode và tốc độ tăng của named volumes/logs.
- Health status, startup time, dependency errors và request latency/error rate.
- Port collision, network/DNS failure, image pull/build failure và time-to-recover sau restart.
6. Practical workflow
- Viết
compose.yamlvới service/network/volume tối thiểu cần thiết. - Đặt biến local vào
.envhoặc--env-file; đưa secret ra cơ chế secret phù hợp. - Chạy
docker compose configđể xem model sau merge/interpolation. - Chạy
docker compose up -d; kiểm tradocker compose psvà health status. - Kiểm tra log bằng
docker compose logs --tail=200 <service>khi startup thất bại. - Inject failure: restart dependency, dừng một service hoặc làm healthcheck fail; xác nhận client retry/reconnect đúng kỳ vọng.
- Dùng
docker compose downđể dừng/xóa containers và networks; chỉ dùng-vkhi thật sự muốn xóa named volumes.
docker compose config
docker compose up -d
docker compose ps
docker compose logs --tail=200 api
docker compose restart db
# Verify: api reconnects/retries without corrupting work
docker compose down
# Destructive for project named volumes:
# docker compose down -v
7. Checklist
- Service dùng DNS name thay vì hard-code container IP.
depends_onkhông bị hiểu nhầm là guarantee availability suốt runtime.- Healthcheck đo readiness thật và có timeout/retry hợp lý.
- Application có bounded retry/backoff/reconnect cho dependency transient failure.
docker compose configđược dùng để review model sau merge/interpolation.- Secret không commit vào repo hoặc nhét mặc định trong
.env. - Image version được kiểm soát; network/port exposure theo least privilege.
- Named volume có ownership, backup/restore và quy tắc xóa rõ ràng nếu dữ liệu quan trọng.
- Team hiểu Compose là single-host application tooling, không phải HA orchestration.