مدیریت وابستگی‌ها در Docker Compose

مشکل اصلی

وقتی با docker compose up چند سرویس را بالا می‌آوری (مثلاً API، Postgres، Redis)، Compose فقط کانتینرها را استارت می‌کند اما آماده شدن سرویس داخل کانتینر زمان می‌برد.

مثال واقعی:

Postgres container started   (1s)
Postgres ready for queries   (6s)

اگر API در ثانیه 2 بخواهد وصل شود:

connection refused

پس باید somehow بگوییم: صبر کن تا دیتابیس واقعاً آماده شود.

1. depends_on (فقط ترتیب)

ساده‌ترین حالت:

services:
  api:
    build: .
    depends_on:
      - db

  db:
    image: postgres

معنی:

اول db
بعد api

اما مشکل:

db started (بله)
db ready (خیر)

پس depends_on به تنهایی کافی نیست.

2. healthcheck (بگو چه زمانی آماده است)

اینجا به Docker یاد می‌دهیم که چه زمانی سرویس واقعاً آماده است.

مثال برای postgres:

services:
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      retries: 5

یعنی:

  • هر 5 ثانیه چک کن
  • آیا postgres آماده است؟
  • وقتی آماده شد وضعیت می‌شود: healthy

3. وصل کردن depends_on به healthcheck

حالا می‌توانیم بگوییم: API فقط وقتی شروع شود که db سالم باشد

services:
  api:
    build: .
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]

حالا ترتیب واقعی می‌شود:

start db
↓
healthcheck اجرا می‌شود
↓
db healthy
↓
start api

این بهترین روش در بیشتر پروژه‌هاست.

4. wait-for-it (روش داخل خود برنامه)

یک روش دیگر این است که خود برنامه صبر کند.

مثال:

services:
  api:
    build: .
    command: ["./wait-for-it.sh", "db:5432", "--", "npm", "start"]
    depends_on:
      - db

  db:
    image: postgres

یعنی:

اول صبر کن db:5432 باز شود
بعد برنامه را اجرا کن

flow:

api start
↓
wait-for-it
↓
db ready
↓
run app