はじめに
以下のようなdocker-compose.yaml
があった時に、app
(アプリ)の起動時にはそのアプリが依存するMySQLやRedisが立ち上がった状態になっていてほしいことはままある。
version: '3.9'
services:
app:
container_name: app
image: app:latest
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:3000
redis:
image: redis:7.2.1-alpine3.18
container_name: redis
environment:
TZ: 'Asia/Tokyo'
volumes:
- ./data/redis:/data
ports:
- 6379:6379
mysql:
image: mysql:8.0.32
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ''
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
TZ: 'Asia/Tokyo'
ports:
- 3306:3306
volumes:
- ./data/mysql:/var/lib/mysql
- ./mysql/sql:/docker-entrypoint-initdb.d
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
そのような場合に、どうしたら依存サービスの起動(正確にはスタンバイ)を待ってアプリのコンテナを起動するようにできるか?について、今回は見ていきたいと思う。
healthcheckとdepends_onを利用する
結論としては、以下のようにhealthcheck
とdepends_on
を利用すればいい。
version: '3.9'
services:
app:
...
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
ports:
- 8080:3000
redis:
...
healthcheck:
test: ['CMD', 'redis-cli', 'ping']
interval: 10s
timeout: 5s
retries: 3
...
mysql:
...
healthcheck:
test: ['CMD', 'mysqladmin', 'ping', '-h', 'localhost']
interval: 10s
timeout: 5s
retries: 3
...
以下で詳細を見ていく。
healthcheck
healthcheck declares a check that's run to determine whether or not the service containers are "healthy".
と書かれている通り、healthcheckによりコンテナが正常に起動していることを確認できる。そのコマンドはtest
のキーに定義することができ、このコマンドをcomposeが実行してくれる(ちなみに、Dockerfile内のHEALTHCHECKはcomposeで定義されているものがあれば上書きされる)。
具体的に今回の例で見ていくと、MySQL・Redisでそれぞれ以下のようなことをしている。
- MySQL
-
mysqladmin ping -h localhost
:mysqladminコマンドでMySQLサーバーにpingを送り、その応答を確認する(詳細は4.5.2 mysqladmin — A MySQL Server Administration Programを参照)
-
- Redis
-
redis-cli ping
:redis-cliコマンドでRedisサーバーにpingを送り、その応答を確認する(詳細はRedis CLIを参照)
-
つまりは、それぞれのサーバーでpingをして応答を確かめている。
そして、interval
, timeout
, retries
はそれぞれ以下のことを設定している。
- interval:testに設定されたコマンドをどれくらいのサイクルで実行するか?を設定する。コンテナが起動してからインターバル秒後に最初に実行され、前回のチェックが完了するたびにインターバル秒後に再度実行される。
- timeout:testに設定されたコマンドを実行した際に、そのコマンドの実行にどれだけ時間がかかったら失敗とみなすか?を設定する。タイムアウト秒数以上かかった場合、チェックは失敗したとみなされる。
- retries:コンテナが
unhealthy
と判定されたときに、何回testに設定されたコマンドを実行するか?を設定する。
depends_on
続いてdepends_on
についてだが、以下のように記載がある通り、コンテナサービス間のスタート・シャットダウンの順番の制御に関わる設定になる。
depends_on expresses startup and shutdown dependencies between services.
condition
にservice_healthy
を指定することで、依存サービスを開始する前に、依存関係(今回でいうとMySQL・Redisのそれぞれ)がhealthcheckの設定で定義される条件を満たし、healthyであるか?をチェックし、healthyの場合にコンテナを起動するという設定をすることができる。
まとめとして
上記のそれぞれの設定を組み合わせることで、MySQL・Redisのそれぞれがhealthcheckの結果、healthyとみなされる=問題なく起動しスタンバイになっている場合に、アプリのコンテナを起動させることができるようになる。