Docker Compose 啟動順序怎麼等服務就緒:healthcheck 與 service_healthy
docker compose up 看到資料庫容器已經 running,但 app 立刻連線失敗,通常不是 depends_on 沒寫,而是把「容器已啟動」誤當成「服務已就緒」。Compose 會按 dependency order 建立服務,卻不會預設等待資料庫真的能處理 SQL。
解法是:**在被依賴的服務定義能代表可用狀態的 healthcheck,依賴端再用 condition: service_healthy。**這可消除啟動時的競態,但不取代 app 自己對暫時性斷線的重試策略。
把資料庫的可用條件寫成 healthcheck
以下 PostgreSQL 範例以 pg_isready 檢查連線能力;注意 $${...} 的雙錢號,讓 Compose 不要在解析 YAML 時先替換環境變數。
services: db: image: postgres:18 environment: POSTGRES_USER: app POSTGRES_DB: app healthcheck: test: ['CMD-SHELL', 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}'] interval: 10s timeout: 10s retries: 5 start_period: 30shealthcheck 應測真正的相依條件,不要只測 process 是否存在。對 Redis 可用 redis-cli ping;對 HTTP API 可用一個不需登入、能反映必要依賴的 health endpoint。
讓 app 等到健康狀態
services: app: build: . depends_on: db: condition: service_healthy restart: trueservice_healthy 會讓 Compose 等到 db 的 healthcheck 成功才建立 app。restart: true 的意義較窄:當你明確用 Compose 操作更新或重啟 dependency 時,依賴端也會被重啟以重新建立連線;它不是容器崩潰時的萬用修復機制。
不要把啟動等待當成連線韌性
運行中的資料庫仍可能因網路、重啟或維護而暫時不可用。app 的 database client 仍需要適合自身協議的 timeout、重試與錯誤回應;Compose 的 healthcheck 只處理 up 當下的依賴就緒順序。
先用以下指令確認 Compose 實際解析結果與健康狀態:
docker compose configdocker compose up -ddocker compose psdocker compose logs app db若 stack 還分散在多個 Compose 檔,先檢查 Docker Compose include 的路徑與變數邊界;拆檔正確不會自動處理服務就緒,兩者要分開驗證。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。