【DOCKER】Dockerのヘルスチェックとは?

docker

🐳 Dockerのヘルスチェックとは?

コンテナの起動タイミングを制御する実践ガイド

問題の発生

Dockerで少し複雑な環境を構築していると、少し困った事が起きました。

サーバーを建てて、サーバー内で以下のコマンドを実行させているのですが:

chown www:www /run/php-fpm/www.sock
chmod 777 /run/php-fpm/www.sock
問題: サーバーを建てている途中に、このシェルが走ってしまうようで、毎回エラーになる。

感覚的には3秒ほど待ってから実行すればいけると思う。

解決策:ヘルスチェック

Dockerで、ビルドが終わってから、次の命令を実行させる方法はないか探していたところ、「healthcheck」という方法があるらしい。

ただ、この方法結構マニアックなやり方らしく、Dockerの本3冊位読んで勉強したけど、こんなの出てきたかなと…。

ネットで探しても「意味ない」「使い方わからん」のような記事が出てくる。

わからんので検証してみる。

ヘルスチェックの基本

書き方

healthcheck:
  test: ["CMD", "sh", "-c", "db2 connect to testdb"]
  interval: 1s
  timeout: 1s
  retries: 10
  start_period: 1s

📝 コマンドの意味

  • test:ヘルスチェックをするコマンド内容を書く
  • interval:testのコマンドの実行間隔、5sと書いたら5秒に一回コマンドを実行する
  • timeout:タイムアウトの時間、この時間内にコマンドが成功しないと、またintervalに戻る
  • retries:リトライする回数、3と書いたら、3回失敗したらステータスが「ヘルシーじゃない」となる
  • start_period:最初のコマンドを実行するまでの時間

実践:WordPressでの検証

ヘルスチェックなしの場合

services:

  wordpress:
    image: wordpress:latest
    ports:
      - "80:80"
    volumes:
      - ./www:/var/www/html
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_USER: test
      WORDPRESS_DB_PASSWORD: test
      WORDPRESS_DB_NAME: test
    depends_on:
      - mysql

  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: test
      MYSQL_USER: test
      MYSQL_PASSWORD: test
      MYSQL_DATABASE: test

問題点:

このDocker、もちろん成功するのですが、1点問題があります。

ビルドが終わってすぐにアクセスすると http://localhost/ でエラーになります。

3秒くらい待ってからアクセスすると成功する。

つまり、MySQLの起動が終わってないのにビルドが終わってしまう。

エラー画面の例

ヘルスチェックありの場合

MySQLの起動が終わってから、ビルド完了させたい。では、WordPressのYMLファイルにヘルスチェックを入れてみます。

services:

  wordpress:
    image: wordpress:latest
    ports:
      - "80:80"
    volumes:
      - ./www:/var/www/html
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql:3306
      WORDPRESS_DB_USER: test
      WORDPRESS_DB_PASSWORD: test
      WORDPRESS_DB_NAME: test
    depends_on:
      mysql:
        condition: service_healthy

  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: test
      MYSQL_USER: test
      MYSQL_PASSWORD: test
      MYSQL_DATABASE: test
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "mysql", "-u", "test", "-ptest"]
      interval: 2s
      timeout: 10s
      retries: 3
      start_period: 1s

これでビルドしてみます:

docker-compose up -d

すると5秒くらいですがWaitingになります。

Waiting画面の例

少し待つとMySQLがHealthyとなる。

Healthy画面の例

すぐにlocalhostにアクセスしてみると…

✅ エラーにならず接続出来た!!
成功画面の例

Dockerfileでヘルスチェック

YMLファイルでのヘルスチェックはわかりました。これは全然使える。

でも、環境構築が大きくなると、Dockerfileでヘルスチェックしたい時もある

抱えている問題

大きめの環境構築で、Dockerfileでシェルを読ませて、その後にさらに権限変更をやらせようとしています。

ENTRYPOINT ["/docker-entrypoint.sh"]

RUN chown www:www /run/php-fpm/www.sock
RUN chmod 777 /run/php-fpm/www.sock
ただ、これは上手くいかず、アクセスするとエラーになってしまう。
エラー画面の例 手動でコマンドを実行すればアクセス出来るようになるのですが、これをヘルスチェックでやらせてみたい。

解決方法

Dockerfileの最後に以下を追加:

# 構築に時間がかかるので構築終わってからの処理をヘルスチェックで対応
HEALTHCHECK --interval=5s --timeout=3s --retries=5 \
  CMD test -S /run/php-fpm/www.sock && chown www:www /run/php-fpm/www.sock && chmod 777 /run/php-fpm/www.sock || exit 1
✅ これで、15秒ほど待ってからアクセスすると成功します!!

📝 仕組みの説明

  • HEALTHCHECK --interval=5s --timeout=3s --retries=5 で処理の時間を決定
  • その後の && ~~~~~~~~ || exit 1 ここの「~~~~」に成功した場合の処理を書く
  • 成功するまで繰り返してくれるので、かなり使える

まとめ

  • ヘルスチェックは、コンテナの起動タイミングを制御するための強力なツール
  • docker-compose.ymlとDockerfileの両方で使用可能
  • マニアックだが、複雑な環境構築では必須のテクニック
  • 成功するまで繰り返し実行してくれるので、タイミング問題を解決できる

コメント