Bạn chạy docker compose up cho stack app + database, container app lên trước vài giây và fail ngay vì DB chưa ready. Đây là lỗi rất phổ biến khi triển khai local lẫn production nhỏ. Bài này hướng dẫn cách xử lý chuẩn bằng depends_on kết hợp healthcheck để startup order hoạt động đúng như kỳ vọng.
Vì sao depends_on một mình chưa đủ?
Trong Docker Compose, depends_on giúp xác định thứ tự tạo service, nhưng mặc định chỉ đảm bảo service phụ thuộc đã “running”, không đảm bảo “ready”.
Ví dụ DB container đã chạy nhưng Postgres vẫn đang khởi tạo WAL, apply config hoặc tạo user. Nếu app connect ngay lúc đó, bạn gặp lỗi:
connection refusedtimeout expireddatabase system is starting up
Prerequisites
- Docker Engine + Docker Compose plugin mới
- File
compose.yaml - App có cơ chế retry kết nối DB (khuyến nghị)
Cấu hình mẫu: web phụ thuộc Postgres và Redis
services:
web:
build: .
depends_on:
db:
condition: service_healthy
restart: true
redis:
condition: service_started
environment:
DB_HOST: db
REDIS_HOST: redis
db:
image: postgres:16
environment:
POSTGRES_DB: appdb
POSTGRES_USER: appuser
POSTGRES_PASSWORD: supersecret
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
redis:
image: redis:7
Ý nghĩa nhanh
service_healthy: chờ DB pass healthcheck rồi mới start webservice_started: chỉ cần Redis đã chạyrestart: truedưới dependency: khi bạn chủ động restart/updatedbqua Compose operation,webcũng được restart để reconnect sạch
Startup order khuyến nghị cho stack phổ biến
- Stateful services: DB, queue, cache
- Migration job (nếu có)
- API service
- Worker/cron service
Nếu có migration riêng, dùng service_completed_successfully cho migration job để API chỉ chạy khi migrate thành công.
Mẫu với migration service
services:
migrate:
image: myapp:latest
command: ["sh", "-c", "./migrate.sh"]
depends_on:
db:
condition: service_healthy
api:
image: myapp:latest
depends_on:
migrate:
condition: service_completed_successfully
Cách này giảm tình trạng API lên trước khi schema sẵn sàng.
Troubleshooting: app vẫn lỗi dù đã có healthcheck
1) Healthcheck “pass giả”
pg_isready pass nhưng schema/changelog chưa xong. Cách xử lý:
- Tách migration service riêng
- App có startup retry 30-60 giây
2) start_period quá ngắn
DB nặng dữ liệu có thể cần lâu hơn để ổn định. Tăng start_period và retries.
3) App fail-fast không retry
Compose không thay thế retry logic trong app. Nên cấu hình:
- Exponential backoff
- Max retry hợp lý
- Log rõ nguyên nhân kết nối
4) Nhầm biến môi trường trong healthcheck
Dùng $$ trong YAML để escape biến shell đúng cách:
- Đúng:
$${POSTGRES_USER} - Sai:
${POSTGRES_USER}(có thể bị compose interpolate sai ngữ cảnh)
Best practices production nhỏ
- Luôn có
healthcheckcho DB, cache, API - Tách migration thành service riêng
- Không hardcode secret trong compose file
- Dùng
.envhoặc secret manager - Theo dõi log startup bằng
docker compose logs -f
FAQ — docker compose startup order
1) depends_on có chờ service ready không?
Mặc định không. Cần condition: service_healthy + healthcheck.
2) Có cần retry trong app nữa không?
Có. Retry trong app vẫn cần để chống network jitter và race condition hiếm.
3) Khi nào dùng service_completed_successfully?
Khi service phụ thuộc là one-shot job như migrate schema hoặc init data.
4) restart: true trong depends_on dùng để làm gì?
Giúp service phụ thuộc (ví dụ web) restart theo khi dependency bị restart/update qua thao tác Compose.
5) Có nên dùng script wait-for-it.sh thay healthcheck?
Có thể dùng, nhưng healthcheck + condition là cách native, rõ ràng và dễ maintain hơn.
Kết luận
Nếu bạn muốn stack ổn định ngay từ lệnh docker compose up, hãy xem startup order như một phần thiết kế hệ thống, không phải vá lỗi sau cùng. Cặp depends_on + healthcheck giải quyết phần lớn lỗi kết nối lúc boot, còn retry trong app giúp hệ thống “chịu đựng” tốt khi môi trường thực tế biến động.
—
# IMAGE PLAN
- Featured keyword: docker containers monitoring dashboard on laptop, server room background
- Inline 1 keyword: postgres database server rack blue lighting
- Inline 2 keyword: software engineer terminal docker compose logs
- Inline 3 keyword: microservices architecture diagram no text minimal
- Alt text mẫu:
– docker compose startup order – giám sát container khi khởi động – docker compose startup order – postgres healthcheck trước khi app chạy – docker compose startup order – kiến trúc service phụ thuộc trong stack
# SOURCES
- Docker Docs: https://docs.docker.com/compose/how-tos/startup-order/
