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 が先に起動してしまう、あるいはいつまでも起動しない、という場合は次の順に確かめます。
- healthcheck の状態を見る:
docker compose psの STATUS 列に(healthy)や(health: starting)、(unhealthy)が表示されます。unhealthyのままなら、依存元はいつまでも起動しません。 - healthcheck の実行結果を見る:
docker inspect --format '{{json .State.Health}}' <コンテナ名>で、直近の実行の終了コードと出力を確認できます。コマンドが見つからない(イメージにツールが入っていない)、認証で失敗している、といった原因がここで分かります。 - 合成後の設定を見る:
docker compose configで、実際に使われる設定を表示できます。インデントの誤りでconditionが別の場所に入っている、といった間違いはここで見つかります。 - ログを見る:
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の順に確かめる - 運用中の再接続に備え、アプリ側の再試行も用意する