Docker Compose の depends_on の使い方まとめ
Docker Compose の depends_on
の使い方をかんたんにまとめました。
主に自分用のまとめですが、このあたりは公式ドキュメントがあまり充実していないので、 Docker Compose をよく使う方のお役にも立つのではないかと思います。
前提
Compose ファイル( docker-compose.yml
)のバージョン 3.8 を前提としています。
動作確認には次のバージョンを使用しました:
$ docker --versionDocker version 20.10.5, build 55c4c88$ docker-compose --versiondocker-compose version 1.29.0, build 07737305
depends_on
とは
depends_on
は Docker Compose の各サービスに対して設定できる項目です。
名前が示唆するとおりサービス間の依存関係を指定できます。
たとえば次のように書くと service_b
を service_a
に依存させることができます:
version: "3"services:service_a:image: busyboxservice_b:image: busybox# `service_b` を `service_a` に依存させるdepends_on:- service_a
このように設定すると、 docker-compose up
や docker-compose run
や docker-compose stop
を実行したときに次のような制御が行われます:
docker-compose up
:service_a
→service_b
の順に起動するdocker-compose run
: (docker-compose up
と同じ)docker-compose stop
:serivce_b
→service_a
の順に停止する
depends_on
の指定パターン
depends_on
は次の 2 つのパターンで指定できます。
- Short syntax (リスト)
- Long syntax (オブジェクト)
Short syntax (リスト)
こちらはシンプルな方法で、依存先のサービス名を単純に記述するだけです。
たとえば次のように設定したサービスは service_a
に依存することになります:
depends_on:- service_a
Long syntax (オブジェクト)
こちらは少し複雑な方法で、依存関係にあるサービスをオブジェクト形式で記述するものです。
この方法では依存先に加えて「条件」を指定することができます:
depends_on:service_a:condition: service_started
条件の指定には condition
を使用します。
採りうる選択肢は次の 3 つです:
service_started
service_healthy
service_completed_successfully
condition
にデフォルト値は無いため、 long syntax を選ぶ場合は必ず指定する必要があります。
以下長いので先にまとめですが、それぞれ次のような意味合いになっています:
選択肢 | 説明 |
---|---|
service_started | 依存先のサービスが起動したら起動する |
service_healthy | 依存先のサービスが起動して、なおかつ、 healthcheck が通ったら起動する |
service_completed_successfully | 依存先のサービスが正常終了したら起動する |
以下細かく見ていきます。
1. service_started
service_started
は、依存先のサービスが「起動したこと」を条件とします。
condition: service_started
次のように書くと、 service_a
の起動後に service_b
が起動します:
version: "3"services:service_a:image: busyboxservice_b:image: busyboxdepends_on:service_a:condition: service_started
実行結果:
$ docker-compose up -dCreating network "PROJECT_default" with the default driverCreating PROJECT_service_a_1 ... doneCreating PROJECT_service_b_1 ... done
service_started
で注意すべきポイントは、依存先のサービスが起動したら OK であって、そのメインの処理が「待ち受け状態が整ったこと」を確約するものではない点です。
この挙動は、依存元のサービスが正常な動作をするために依存先のサービスの利用が不可欠な場合に問題になることがあります。
たとえば、次のように書くと、この挙動が問題になりうることが確認できます:
version: "3"services:# service_a: わざと 5 秒待機した後にウェブサーバーを立ち上げるservice_a:image: busyboxcommand:- sh- -c- |set -exsleep 5echo 'Hi' > /var/www/index.htmlhttpd -f -p 80 -h /var/wwwports:- "80:80"# service_b: service_a に対してリクエストをかける# 最初の 1 回だけリクエストが失敗してしまうservice_b:image: busyboxcommand:- sh- -c- |while true; dowget -O- -q http://service_a:80sleep 5donedepends_on:service_a:condition: service_started
この設定で docker-compose up
を実行すると次のようになります:
$ docker-compose upCreating network "PROJECT_default" with the default driverCreating PROJECT_service_a_1 ... doneCreating PROJECT_service_b_1 ... doneAttaching to PROJECT_service_a_1, PROJECT_service_b_1service_b_1 | wget: can't connect to remote host (192.168.240.2): Connection refusedservice_a_1 | + sleep 5service_a_1 | + echo Hiservice_a_1 | + httpd -f -p 80 -h /var/wwwservice_b_1 | Hiservice_b_1 | Hi
Connection refused
ということで、最初の 1 回だけ service_b
の wget
のリクエストが失敗することが確認できます。
なお、 depends_on
をリスト形式で指定した場合の挙動は、この service_started
を選んだ場合と同じになります。
2. service_healthy
service_healthy
は依存先のサービスが起動してなおかつ healthcheck が通ることを条件とするものです。
condition: service_healthy
healthcheck をパスすることが条件なので、 service_healthy
を利用する場合は依存先のサービスで healthcheck
の設定をしておく必要があります。
参考: healthcheck
| Compose file version 3 reference | Docker Documentation
次のように書くと、 service_a
の healthcheck が通った後に service_b
が起動します:
version: "3"services:service_a:image: busybox# かんたんに状態を Up に保つためのに httpd を使用するcommand: httpd -fhealthcheck:test: exit 0# すぐに結果が出るようにタイミングを調整するinterval: 1stimeout: 1sretries: 3start_period: 1sservice_b:image: busyboxdepends_on:service_a:condition: service_healthy
実行結果:
$ docker-compose up -dCreating network "PROJECT_default" with the default driverCreating PROJECT_service_a_1 ... doneCreating PROJECT_service_b_1 ... done
service_healthy
では service_started
の場合とは異なり、次のような場合には対象のサービスは起動しません。
- healthcheck が通らなかった場合
- 依存先サービスの処理が終了してコンテナが停止した場合
たとえば次のように書くと、 service_a
は正常に動いていますが healthcheck が通らないので service_b
は起動しません:
version: "3"services:service_a:image: busybox# かんたんに状態を Up に保つためのに httpd を 使用するcommand: httpd -f# healthckeck が通らないようにあえて exit 1 を実行するhealthcheck:test: exit 1# すぐに結果が出るようにタイミングを調整するinterval: 1stimeout: 1sretries: 3start_period: 1sservice_b:image: busyboxdepends_on:service_a:condition: service_healthy
この設定で docker-compose up -d
を実行した後に docker-compose ps
を実行すると、 service_a
の state 判定が Up (unhealthy)
となっていること、そして、 service_b
が起動していなかったことが確認できます:
$ docker-compose psName Command State Ports------------------------------------------------------PROJECT_service_a_1 httpd -f Up (unhealthy)
また、次のように書いた場合は、 service_a
が( sh
を実行して)すぐに停止してしまうので、こちらも service_b
は起動しません:
version: "3"services:service_a:image: busyboxhealthcheck:test: exit 0# すぐに結果が出るようにタイミングを調整するinterval: 1stimeout: 1sretries: 3start_period: 1sservice_b:image: busyboxdepends_on:service_a:condition: service_healthy
3. service_completed_successfully
service_completed_successfully
は依存先のサービスが正常に終了したことを条件とするものです。
condition: service_completed_successfully
service_completed_successfully
の場合は依存先のサービスが「終了すること」が必要なので service_started
や service_healthy
とは毛色・使いどころがかなり異なります。
次のように書くと、 service_a
が起動してすぐに停止した後に service_b
が起動します:
version: "3"services:# service_a: すぐに正常終了させるservice_a:image: busyboxcommand: ["sh", "-c", "exit 0"]service_b:image: busyboxdepends_on:service_a:condition: service_completed_successfully
次のように書くと、 service_a
が異常終了するので service_b
は起動しません:
version: "3"services:# service_a: 異常終了させるservice_a:image: busyboxcommand: ["sh", "-c", "exit 1"]service_b:image: busyboxdepends_on:service_a:condition: service_completed_successfully
また、次のように書くと、 service_a
が終了しないのでいくら待っても service_b
は起動してきません:
version: "3"services:# `service_a` を終了させないservice_a:image: busyboxcommand: ["sh", "-c", "while true; do echo Hello; sleep 5; done"]service_b:image: busyboxdepends_on:service_a:condition: service_completed_successfully
ちなみに、この service_completed_successfully
は 2021 年 2 月に仕様として追加 & 実装された比較的新しい機能です。
docker-compose
ではバージョン 1.29.0 ( 2021/04/06 リリース)以降で使えるようになっています。
「 Kubernetes の Init Containers に似た機能を Docker Compose でも使いたい」という考えからリクエストがあり追加されたようです。
参考:
- 1.29.0 | Docker Compose release notes | Docker Documentation
- Feature Request: Init Containers for Docker Compose · Issue #6855 · docker/compose · GitHub
- Add a dependsOn condition to wait for successful completion by mikesir87 · Pull Request #134 · compose-spec/compose-spec · GitHub
- Add init container support by ojab · Pull Request #8122 · docker/compose · GitHub
ということで Docker Compose の depends_on
のまとめでした。
正確な仕様は compose-spec
を参照してください。
参考
compose-spec/spec.md
at master ·compose-spec/compose-spec
· GitHubdepends_on
| Compose file version 3 reference | Docker Documentation
compose-spec
の spec.md
が最も正確なドキュメントのようです。