492 字
2 分鐘

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: 30s

healthcheck 應測真正的相依條件,不要只測 process 是否存在。對 Redis 可用 redis-cli ping;對 HTTP API 可用一個不需登入、能反映必要依賴的 health endpoint。

讓 app 等到健康狀態#

services:
app:
build: .
depends_on:
db:
condition: service_healthy
restart: true

service_healthy 會讓 Compose 等到 db 的 healthcheck 成功才建立 apprestart: true 的意義較窄:當你明確用 Compose 操作更新或重啟 dependency 時,依賴端也會被重啟以重新建立連線;它不是容器崩潰時的萬用修復機制。

不要把啟動等待當成連線韌性#

運行中的資料庫仍可能因網路、重啟或維護而暫時不可用。app 的 database client 仍需要適合自身協議的 timeout、重試與錯誤回應;Compose 的 healthcheck 只處理 up 當下的依賴就緒順序。

先用以下指令確認 Compose 實際解析結果與健康狀態:

Terminal window
docker compose config
docker compose up -d
docker compose ps
docker compose logs app db

若 stack 還分散在多個 Compose 檔,先檢查 Docker Compose include 的路徑與變數邊界;拆檔正確不會自動處理服務就緒,兩者要分開驗證。

參考資料:

Docker Docs:Control startup and shutdown order

Docker Docs:Compose healthcheck

Docker Compose 啟動順序怎麼等服務就緒:healthcheck 與 service_healthy
https://laplusda.com/posts/docker-compose-healthcheck-startup-order/
作者
Zero
發佈於
2026-08-02
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。