Composeの起動順とhealthcheck: 起動済みと準備完了は別

公開日: 2026-09-12 #Docker Compose #healthcheck #n8n #PostgreSQL

Composeでデータベースを先に起動しても、アプリが接続できる時刻まで待つとは限らない。Docker公式は、Composeが通常待つのはコンテナがrunningになるまでで、サービスの準備完了ではないと説明している。外部AI APIを呼ぶワークフローでは、再起動直後だけ失敗する原因になりやすい。

この違いを確認するため、次の表を公式仕様から整理した。動作結果を伴うベンチマークではない。確認日: 2026年9月12日。Docker公式: Composeの起動順と終了順

状態 何が起きているか 依存する側を起動してよいか
作成済み コンテナ定義が作られた まだ判断しない
起動済み プロセスが動き始めた DB初期化中なら早すぎる
healthy 定義したhealthcheckが通った healthcheckの意味が接続可能と一致するなら候補になる
完了成功 一回限りの初期化処理が成功終了した 初期化を待つ依存先に使える

depends_on は順番だけでは足りない

depends_on を書くと依存関係に沿ってサービスを作成・停止できる。しかし、単に依存先を列挙しただけでは「データベースがSQLを受けられる」状態を待たない。依存先が起動プロセスの途中なら、アプリは接続失敗を記録して終了したり、再試行の設定次第で不安定になったりする。

準備完了を待ちたい依存先には healthcheck を定義し、依存側で condition: service_healthy を選ぶ。初期スキーマ作成のように一度だけ成功終了してほしい処理には、service_completed_successfully が意味に合う場合がある。反対に、単にプロセスがいれば足りる依存先では service_started で足りる。

healthcheckは「プロセスがいるか」ではなく利用可能かを見る

healthcheckの内容が浅いと、healthyの表示に安心してしまう。HTTPサーバーなら、アプリが必要とするエンドポイントが応答するか。PostgreSQLの pg_isready はサーバーが接続を受け付けているかを調べるコマンドで、正しいユーザー名、パスワード、データベース名を与えなくても状態確認ができる。つまり、これだけではアプリ用アカウントの認証成功やSQL実行まで保証しない。依存側が必要とする条件を確認項目にする。PostgreSQL公式: pg_isready

次は既存の db サービスへ置く healthcheck と、依存側の depends_on だけを抜き出した例である。単独で起動するComposeファイルではない。イメージ、環境変数、volumeなどは採用するDBの公式手順に従って別途定義する。バージョンは、採用前に公式イメージのリリース情報と自分の互換性を確認して固定する。

# dbサービス内
healthcheck:
  test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -p 5432"]
  interval: 10s
  timeout: 10s
  retries: 5
  start_period: 30s

# dbへ依存するサービス内
depends_on:
  db:
    condition: service_healthy

pg_isready は、使うイメージに含まれることと、待受ポートが実際の設定と一致することを確認して使う。healthcheckを通すためだけに認証を緩めたり、アプリの本来の失敗を隠したりしない。

再起動後の確認は三段に分ける

一段目では、Composeのサービスが期待した状態へ移ったかを確認する。二段目では、アプリ用アカウントで認証し、必要なテーブルへ読み書きできることを確認する。三段目で、外部へ送らないテストデータを使い、利用経路の処理を一件だけ通す。n8nなら、画面が開くことと、Webhookを受けてAI APIへの呼び出しまで成功することは別の確認になる。データベースを使うアプリなら、接続ログ、キュー、保存先も対象に含める。

確認の順番を運用メモに残すと、障害時に「コンテナは動いているのに処理が進まない」を切り分けやすい。失敗通知を扱うワークフローは、依存サービスが準備できないときの再試行回数や、二重実行の防止も設計へ入れる。

参考資料