【2026年版】Docker Composeで起動順序を確実に制御する|depends_onだけでは足りない

当ページのリンクには広告が含まれています。
docker compose startup order 2026
🔧 インフラエンジニア歴12年(2026年時点)☁️ AWS実務4年目(2026年時点)🐳 Docker実務運用

複数コンテナ構成でいちばん多い事故は「DBが起動する前にアプリが接続しにいって落ちる」です。depends_on を書いただけでは防げません——あれはコンテナの起動を待つだけで、中のサービスが使える状態かは見ていないからです。解決は healthcheck + condition: service_healthy の組み合わせです。

「ローカルでは動くのに、compose up すると初回だけ失敗する」——このパターンはほぼ起動順序の問題です。しかも2回目以降は成功するので原因が見えにくい。この記事では順序制御を確実にする書き方を扱います。

目次

depends_on だけでは足りない理由

Compose v1の depends_on はコンテナが起動したことしか待ちません。PostgreSQLのコンテナが立ち上がっても、内部の初期化が終わってなければ接続は拒否されます。

結果として、APIコンテナが接続を試みた瞬間にDBがまだ準備できていない——というレース条件が発生します。マシンの速度や初回起動かどうかで結果が変わるので、再現性が低く厄介です。

Compose v2の改善点

v2で入った depends_on の condition キーが、この問題への公式な答えです。「起動を待つ」から「使える状態になるのを待つ」へ条件を指定できるようになりました。

healthcheckの書き方

依存される側(DBなど)に healthcheck を定義します。これが無いと service_healthy は使えません。

項目 意味
test 健全性を判定するコマンド
interval チェックの実行間隔
timeout 1回の結果を待つ時間
retries unhealthy と判定するまでの連続失敗回数
start_period 起動直後の猶予時間(この間の失敗は回数に数えない)
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

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

start_period を軽視しない

初期化に時間がかかるサービスでは、起動直後の失敗が retries を食い潰して unhealthy 扱いになります。start_period はその期間の失敗を回数にカウントしません。DBやElasticsearchのように立ち上がりが重いものでは、ここを適切に取るだけで安定します。

マイグレーションの完了を待つには

「DBが立ち上がる → マイグレーションを流す → アプリを起動する」という3段構えでは、真ん中のワンショットコンテナの終了を待つ必要があります。

これには condition: service_completed_successfully を使います。指定したサービスが正常終了するまで待ってから起動します。

services:
  migrate:
    build: .
    command: ["./migrate.sh"]
    depends_on:
      db:
        condition: service_healthy

  api:
    build: .
    depends_on:
      migrate:
        condition: service_completed_successfully
condition 待つもの 使いどころ
service_started コンテナの起動 順序だけ揃えばいい場合
service_healthy healthcheckの成功 DB・キャッシュなど接続先
service_completed_successfully 正常終了 マイグレーション・初期化ジョブ

それでも落ちる場合は

健全性チェックが本当に「使える」を見ているか

プロセスが生きているかだけを見るヘルスチェックは、起動途中でも成功してしまいます。PostgreSQLなら pg_isready、HTTPサービスなら実際にエンドポイントを叩くなど、依存側が実際に使う経路で判定するようにしてください。

加えて、アプリケーション側にリトライを実装しておくのが本来の堅牢さです。本番ではDBの再起動やネットワークの瞬断が起こるので、起動順序の制御だけに頼る設計は脆いです。Composeの順序制御は「開発体験を良くするもの」、リトライは「本番で落ちないためのもの」と役割を分けて考えてください。

合わせて整えると効くこと

  • イメージを軽くする——起動が速くなれば順序問題そのものが起きにくくなります(Dockerfile最適化のテクニック)。
  • 環境ごとに設定を分ける——開発と本番でヘルスチェックの間隔を変えたいことがあります。
  • ログを見る癖をつける——「なぜ unhealthy なのか」はヘルスチェックコマンドの出力に出ています。

VPS上での本番公開まで含めた構成はVPSにDocker+Nginx+SSLで公開する手順にまとめました。

UdemyでDockerの講座を探す※ 単品購入した講座は条件を満たせば30日以内に返金可・購入前に一部レクチャーを無料プレビューできます

まとめ

depends_on は起動を待つだけ。使える状態を待たせたいなら healthcheck + condition: service_healthy、ジョブの完了を待たせたいなら condition: service_completed_successfully。この2つで大半の順序問題は解決します。

そして start_period を忘れないこと。立ち上がりの重いサービスでは、ここが無いだけで不安定になります。最後に、本番を見据えるならアプリ側のリトライも併せて実装してください。

depends_onを書いたのに接続エラーで落ちます。
depends_onはコンテナの起動を待つだけで、中のサービスが接続可能になったかは見ていません。依存先にhealthcheckを定義し、depends_onで condition: service_healthy を指定してください。これで実際に接続できる状態になってから起動します。
start_periodは何のための設定ですか?
コンテナ起動直後の猶予時間です。この期間中のヘルスチェック失敗はretriesの回数にカウントされません。DBやElasticsearchのように初期化が重いサービスでは、これが無いと起動途中の失敗でretriesを使い切ってunhealthy扱いになってしまいます。
マイグレーションの完了を待たせるにはどうしますか?
condition: service_completed_successfully を使います。指定したサービスが正常終了するまで待ってから起動するため、ワンショットのマイグレーションコンテナや初期化ジョブに適しています。service_healthyは常駐サービス向けで、終了するコンテナには使えません。
healthcheckを設定しても不安定です。
ヘルスチェックの中身が「使える状態」を判定できていない可能性があります。プロセスの生存確認だけでは起動途中でも成功してしまうため、PostgreSQLならpg_isready、HTTPサービスなら実際のエンドポイントを叩くなど、依存側が実際に使う経路で判定してください。加えて本番ではアプリ側のリトライ実装も必要です。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ITインフラエンジニア歴12年、クラウド(AWSがメイン、一部Azure)の実務は4年目(いずれも2026年時点)。社会人向けの3DCGスクールを2026年9月に卒業。Windows 11 + RTX 4070 Ti SUPER の自宅環境で実際に手を動かしながら、インフラ・クラウド・AI・3DCGの技術記事を書いています。

コメント

コメントする

CAPTCHA


目次