2026年9月25日

2026年9月25日

Docker Composeのdepends_onとlinksの使い方|起動順の制御とhealthcheckで「準備完了」を待つ方法

Docker Compose の depends_on は「どのサービスを先に起動するか」を決める設定で、何も指定しなければ相手のコンテナが起動した時点で次に進みます。データベースが接続を受け付けるまで待ちたいなら、healthcheck と condition: service_healthy を組み合わせるのが現在の標準的なやり方です。一方の links は古い仕組みで、新しく書く構成ではほぼ不要です。この記事では、両者の違い、WordPress と MySQL を例にした書き方、うまく待てないときの確かめ方を説明します。

内容は Docker Compose v2(docker compose コマンド)と Compose Specification を前提にしています(2026年10月現在)。古い docker-compose(v1)は保守が終わっているため、使っている場合は先に v2 へ移行してください。

depends_on が保証すること・しないこと

最もよくある誤解は「depends_on を書けば DB の準備ができてからアプリが動く」というものです。短い書き方(リスト形式)が保証するのは次の2点だけです。

  • docker compose up で、依存先のサービスが先に作成・起動される
  • docker compose stop などで、依存元が先に止まる(起動と逆の順)
services:
  wordpress:
    image: wordpress:latest
    depends_on:
      - db
  db:
    image: mysql:8.4

この書き方では、MySQL のコンテナが「起動した」直後に WordPress のコンテナも起動します。MySQL は初回起動時にデータディレクトリの初期化やユーザー作成を行うため、数秒〜数十秒は接続を受け付けません。その間に WordPress が接続を試みると「データベース接続確立エラー」になり、少し待ってから再読み込みすると直る、という現象が起きます。

また docker compose up wordpress のようにサービスを指定して起動した場合も、依存先の db は自動で起動されます。依存先を起動したくないときは --no-deps を付けます。

condition で「準備完了」まで待つ

長い書き方では、依存先がどの状態になったら次へ進むかを condition で指定できます。指定できる値は3種類です。

  • service_started:起動したら進む(短い書き方と同じ)
  • service_healthy:依存先の healthcheck が healthy になるまで待つ
  • service_completed_successfully:依存先が正常終了(終了コード0)するまで待つ

DB を待つ場合は service_healthy を使い、依存先のサービスに healthcheck を定義します。

services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
      WORDPRESS_DB_NAME: wordpress
    depends_on:
      db:
        condition: service_healthy

  db:
    image: mysql:8.4
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
    volumes:
      - db_data:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 --silent"]
      interval: 5s
      timeout: 5s
      retries: 10
      start_period: 30s

volumes:
  db_data:

パスワードは .env ファイルに置き、Git には含めないでください。ここでのポイントは次のとおりです。

  • **-h 127.0.0.1 を使う理由**:公式 MySQL イメージは初期化中、ネットワーク接続を受け付けない一時的なサーバーを動かします。localhost だとソケット経由でその一時サーバーに応答してしまい、初期化が終わる前に healthy になることがあります。TCP で接続する 127.0.0.1 を指定すると、本番のサーバーが起動してから応答するようになります。
  • **start_period**:初回の初期化にかかる時間の猶予です。この間の失敗は retries に数えられません。初期データの投入に時間がかかる場合は長めにします。
  • MariaDB の場合:公式 MariaDB イメージには healthcheck.sh というスクリプトが同梱されており、["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] のように使えます。イメージの版によって有無やオプションが異なるため、使う版のドキュメントで確かめてください。

マイグレーション用の一回だけ動くサービスを先に走らせたい場合は service_completed_successfully が向いています。

services:
  migrate:
    image: my-app:latest
    command: ["php", "migrate.php"]
    depends_on:
      db:
        condition: service_healthy
  app:
    image: my-app:latest
    depends_on:
      migrate:
        condition: service_completed_successfully

restart と required

長い書き方には、ほかに次の2つの項目があります。比較的新しい Compose v2 で追加されたものなので、古い版では使えません(docker compose version で版を確かめてください)。

  • restart: true:docker compose restart db などで依存先が明示的に再起動されたとき、依存元も再起動する
  • required: false:依存先のサービスが起動できなくても警告にとどめ、依存元の起動を続ける

links は何のためにあったか

links は、ユーザー定義ネットワークがなかった時代に、コンテナ同士を名前でつなぐために使われていた仕組みです。

services:
  wordpress:
    image: wordpress:latest
    links:
      - db:database   # 「database」という別名でも db に届く

現在の Compose は、プロジェクトごとに既定のネットワークを作り、同じネットワーク上のサービスはサービス名でそのまま名前解決できます。上の例でも、links がなくても wordpress から db というホスト名で接続できます。そのため新しい構成では links を書く理由はほとんどありません。

links には起動順の依存も暗黙に含まれますが、待つのは「起動」までで、準備完了は待ちません。起動順を表したいなら depends_on、別名で呼びたいならネットワークの aliases を使うほうが意図が明確です。

services:
  db:
    image: mysql:8.4
    networks:
      backend:
        aliases:
          - database
networks:
  backend:

古い構成を引き継いだ場合は、links を削除し、必要なら depends_on と aliases に置き換えると整理できます。

待てていないときの確かめ方

設定したのに WordPress が先に起動してしまう、あるいはいつまでも起動しない、という場合は次の順に確かめます。

  1. healthcheck の状態を見る:docker compose ps の STATUS 列に (healthy) や (health: starting)、(unhealthy) が表示されます。unhealthy のままなら、依存元はいつまでも起動しません。
  2. healthcheck の実行結果を見る:docker inspect --format '{{json .State.Health}}' <コンテナ名> で、直近の実行の終了コードと出力を確認できます。コマンドが見つからない(イメージにツールが入っていない)、認証で失敗している、といった原因がここで分かります。
  3. 合成後の設定を見る:docker compose config で、実際に使われる設定を表示できます。インデントの誤りで condition が別の場所に入っている、といった間違いはここで見つかります。
  4. ログを見る:docker compose logs db で、DB の初期化が終わっているか、エラーで再起動を繰り返していないかを確認します。

起動完了までコマンドを待たせたいときは、docker compose up -d --wait も便利です。サービスが running または healthy になるまで待ってから戻るため、CI でテストを流す前の待機に使えます。

depends_on だけに頼らない

depends_on が効くのは、Compose が起動するときの順番だけです。運用中に DB が再起動すれば、アプリ側は一時的に接続を失います。またコンテナオーケストレーターによって扱いが異なり、たとえば Swarm の docker stack deploy では depends_on は使われず、Kubernetes には同じ設定がありません(Kubernetes では init コンテナなどで待つ設計にします)。

そのため、アプリ側で接続失敗時に再試行する作りにしておくのが堅実です。WordPress はリクエストのたびに DB へ接続するため、DB が戻れば次のリクエストから復帰します。自作のアプリやワーカーでは、起動時に一度接続に失敗しただけで終了する作りを避け、再試行と再起動ポリシー(restart: unless-stopped など)を組み合わせておきます。depends_on と healthcheck は「起動直後の無駄なエラーを減らす仕組み」と考え、アプリの再試行と組み合わせてください。

まとめ

  • depends_on の短い書き方は起動順を決めるだけで、相手の準備完了は待たない
  • DB を待つなら、依存先に healthcheck を定義し condition: service_healthy を使う
  • MySQL の healthcheck は 127.0.0.1 を指定すると、初期化中の誤判定を避けやすい
  • links は古い仕組み。サービス名で名前解決できるので、新しい構成では depends_on とネットワークの aliases を使う
  • 待てないときは docker compose ps、docker inspect の Health、docker compose config の順に確かめる
  • 運用中の再接続に備え、アプリ側の再試行も用意する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲