2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめてのアドベントカレンダーAdvent Calendar 2023

Day 7

docker composeで依存するサービスが起動するまで待機する

Posted at

はじめに

以下のようなdocker-compose.yamlがあった時に、app(アプリ)の起動時にはそのアプリが依存するMySQLやRedisが立ち上がった状態になっていてほしいことはままある。

docker-compose.yaml
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を利用する

結論としては、以下のようにhealthcheckdepends_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
  • 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.

conditionservice_healthyを指定することで、依存サービスを開始する前に、依存関係(今回でいうとMySQL・Redisのそれぞれ)がhealthcheckの設定で定義される条件を満たし、healthyであるか?をチェックし、healthyの場合にコンテナを起動するという設定をすることができる。

まとめとして

上記のそれぞれの設定を組み合わせることで、MySQL・Redisのそれぞれがhealthcheckの結果、healthyとみなされる=問題なく起動しスタンバイになっている場合に、アプリのコンテナを起動させることができるようになる。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?