DockerfileのHEALTHCHECKとは?使い方とdocker inspectによる確認方法を解説


はじめに

Dockerでコンテナを起動した際、コンテナが実行中であっても、内部で動作しているアプリケーションが正常に稼働しているとは限りません。

例えば、Webサーバーのプロセスは起動していても、HTTPリクエストに正常に応答できない状態になっている可能性があります。

このような場合に、コンテナ内のアプリケーションが正常に動作しているかを確認するために使用できるのが、DockerfileのHEALTHCHECK命令です。

HEALTHCHECKを使用すると、コンテナ内で定期的にコマンドを実行し、その実行結果によってコンテナの正常性を確認できます。

本記事では、以下の内容について解説します。

  • HEALTHCHECKとは何か
  • HEALTHCHECKの基本的な書き方
  • --interval、--timeout、--retriesの役割
  • HTTPリクエストを使ったヘルスチェックの設定方法
  • Dockerfileからイメージをビルドする方法
  • コンテナを起動してヘルスチェックを実行する方法
  • docker inspectでヘルスチェックの結果を確認する方法

実際にApache HTTP Serverを使用したDockerfileを作成し、コンテナの状態を確認していきます。

1. DockerfileのHEALTHCHECKとは

HEALTHCHECKは、コンテナ内で定期的にコマンドを実行し、コンテナの正常性を確認するための命令です。

DockerfileにHEALTHCHECKを記述すると、コンテナ起動後に指定したコマンドが一定間隔で実行されます。

例えば、Webサーバーであれば、コンテナ内からHTTPリクエストを送信し、正常に応答できるか確認する方法があります。

次の例を見てみましょう。

HEALTHCHECK --interval=10s --timeout=5s \
    CMD curl -sf http://localhost/ || exit 1

この命令では、コンテナ内からhttp://localhost/にHTTPリクエストを送信し、Webサーバーの応答を確認しています。

curlコマンドが正常に終了すれば、ヘルスチェックは成功と判定されます。

一方、curlコマンドが失敗した場合は、exit 1が実行され、ヘルスチェックは失敗と判定されます。

このように、HEALTHCHECKを設定することで、コンテナが単に起動しているかだけでなく、指定した検査コマンドが正常に実行できるかを確認できます。

1-1. コンテナの起動状態とヘルスチェックの違い

Dockerでは、コンテナが起動しているかどうかを確認するために、次のコマンドを使用できます。

docker ps

ただし、コンテナが起動中であることと、コンテナ内のアプリケーションが正常に応答できることは、必ずしも同じではありません。

HEALTHCHECKを使用すると、コンテナ内部で指定したコマンドの実行結果をもとに、正常性を判定できます。

例えば、HTTPリクエストを送信するヘルスチェックを設定すれば、WebサーバーがHTTPリクエストに応答できるかを検査できます。

なお、ヘルスチェックの結果は、設定したコマンドによる判定です。アプリケーションのあらゆる機能が正常であることを保証するものではありません。

2. HEALTHCHECKの基本構文

HEALTHCHECKは、次の形式で記述します。

HEALTHCHECK [オプション] CMD コマンド

例えば、次のように記述します。

HEALTHCHECK --interval=10s --timeout=5s \
    CMD curl -sf http://localhost/ || exit 1

この例では、コンテナ内でcurlを実行し、Webサーバーの応答を確認します。

HEALTHCHECKで使用する主なオプションは、次の3つです。

オプション説明PDF記載のデフォルト値
--intervalヘルスチェックを実行する間隔30秒
--timeoutヘルスチェックのタイムアウト時間30秒
--retries異常と判定するまでの連続失敗回数3回

それぞれの役割を確認していきましょう。

2-1. –interval:ヘルスチェックの実行間隔

--intervalは、ヘルスチェックを実行する間隔を指定するオプションです。

例えば、次のように記述します。

HEALTHCHECK --interval=10s \
    CMD curl -sf http://localhost/ || exit 1

この例では、ヘルスチェックの実行間隔を10秒に設定しています。

10sのsは秒を表します。

参考資料では、--intervalのデフォルト値は30秒と説明されています。

そのため、実行間隔を指定しなかった場合は、基本的に30秒間隔でヘルスチェックが実行されます。

2-2. –timeout:タイムアウト時間

--timeoutは、ヘルスチェックのタイムアウト時間を指定するオプションです。

例えば、次のように記述します。

HEALTHCHECK --timeout=5s \
    CMD curl -sf http://localhost/ || exit 1

この場合、ヘルスチェックのタイムアウト時間は5秒です。

指定した時間内にヘルスチェックコマンドが完了しなかった場合、そのチェックは失敗と判定されます。

参考資料では、--timeoutのデフォルト値は30秒と説明されています。

2-3. –retries:失敗回数

--retriesは、ヘルスチェックが何回連続して失敗した場合に、コンテナを異常な状態と判定するかを指定するオプションです。

例えば、次のように記述します。

HEALTHCHECK --retries=3 \
    CMD curl -sf http://localhost/ || exit 1

この例では、ヘルスチェックが3回連続で失敗すると、コンテナがunhealthyと判定されます。

参考資料では、デフォルト値は3回と説明されています。

2-4. 複数のオプションを組み合わせる

これらのオプションは、組み合わせて指定できます。

HEALTHCHECK --interval=10s --timeout=5s --retries=3 \
    CMD curl -sf http://localhost/ || exit 1

この例では、次のように設定しています。

  • 10秒間隔でヘルスチェックを実行する
  • 1回のチェックが5秒を超えた場合はタイムアウトする
  • 3回連続で失敗した場合はunhealthyと判定する

このように、オプションを組み合わせることで、ヘルスチェックの実行条件を設定できます。

3. HEALTHCHECKでHTTPリクエストを送信する

参考資料では、Apache HTTP Serverを使用したヘルスチェックの例が紹介されています。

Webサーバーが正常に応答するか確認するために、次のコマンドを使用しています。

curl -sf http://localhost/ || exit 1

このコマンドの内容を確認してみましょう。

3-1. curlコマンドの役割

curlは、HTTPなどのプロトコルを使用して通信するためのコマンドです。

今回の例では、次のコマンドを使用します。

curl -sf http://localhost/

このコマンドは、コンテナ内のlocalhostに対してHTTPリクエストを送信します。

オプションの意味は次のとおりです。

指定説明
curlHTTPリクエストを送信する
-s進捗表示などを抑制する
-fHTTPエラーステータスの場合に失敗として扱う
http://localhost/接続先URL

正常にHTTPリクエストが処理された場合、curlは正常終了します。

一方、接続できない場合やHTTPエラーが発生した場合には、失敗として終了します。

3-2. || exit 1の役割

参考資料では、curlの後ろに次の処理を記述しています。

|| exit 1

||は、前のコマンドが失敗した場合に、後ろのコマンドを実行するためのシェル演算子です。

そのため、次のコマンドでは、

curl -sf http://localhost/ || exit 1

以下のように動作します。

  1. curlでHTTPリクエストを送信する
  2. curlが成功した場合は、正常終了する
  3. curlが失敗した場合は、exit 1を実行する
  4. ヘルスチェックが失敗として判定される

このように、curlの実行結果を利用して、ヘルスチェックの成否を判定しています。

4. HEALTHCHECKを使用したDockerfileを作成する

ここからは、参考資料のApache HTTP Serverの例をもとに、実際にDockerfileを作成します。

参考PDFではCentOS 7を使用していますが、CentOS 7はサポートが終了しているため、現在の開発環境への採用は推奨しません。

ここでは、あくまで参考資料の構成を理解するための例として紹介します。

4-1. 作業ディレクトリを作成する

まず、Dockerfileを配置するディレクトリを作成します。

mkdir docker-healthcheck
cd docker-healthcheck

4-2. Dockerfileを作成する

作業ディレクトリ内にDockerfileという名前のファイルを作成します。

次の内容を記述してください。

FROM centos:7

RUN yum install -y httpd

RUN echo '<h1>OK</h1>' > /var/www/html/index.html

HEALTHCHECK --interval=10s --timeout=5s \
    CMD curl -sf http://localhost/ || exit 1

CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

このDockerfileでは、Apacheをインストールし、HTTPリクエストによるヘルスチェックを設定しています。

なお、参考PDFの例ではcurlを使用していますが、環境によってはcurlの導入状況を別途確認する必要があります。また、CentOS 7のパッケージ取得先の状況によっては、このビルドが成功しない可能性があります。

4-3. Dockerfileの各命令を解説

FROM:ベースイメージを指定

FROM centos:7

CentOS 7のイメージをベースとして使用します。

RUN:Apacheをインストール

RUN yum install -y httpd

Dockerイメージのビルド時にApache HTTP Serverをインストールします。

RUN:HTMLファイルを作成

RUN echo '<h1>OK</h1>' > /var/www/html/index.html

Apacheの公開ディレクトリにindex.htmlを作成します。

このファイルには、次のHTMLが記述されます。

<h1>OK</h1>

HEALTHCHECK:正常性を確認

HEALTHCHECK --interval=10s --timeout=5s \
    CMD curl -sf http://localhost/ || exit 1

10秒間隔でコンテナ内からHTTPリクエストを送信し、正常に応答するか確認します。

CMD:Apacheを起動

CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

コンテナ起動時にApacheをフォアグラウンドで実行します。

5. Dockerイメージをビルドする

Dockerfileを作成したら、Dockerイメージをビルドします。

参考資料では、次のコマンドを使用しています。

docker build -t myapp .

このコマンドの意味は次のとおりです。

指定説明
docker buildDockerfileからイメージをビルドする
-t myapp作成するイメージにmyappという名前を付ける
.現在のディレクトリをビルドコンテキストとして指定する

ビルドに成功すると、myappという名前のDockerイメージが作成されます。

ビルドしたイメージは、次のコマンドで確認できます。

docker image ls

表示される一覧にmyappがあれば、イメージが作成されています。

6. HEALTHCHECKを設定したコンテナを起動する

ビルドしたイメージからコンテナを起動します。

参考資料では、次のコマンドを使用しています。

docker run -d --name cont1 myapp

各指定の意味は次のとおりです。

指定説明
docker runコンテナを作成して起動する
-dバックグラウンドで実行する
--name cont1コンテナ名をcont1にする
myapp使用するDockerイメージ

このコマンドにより、myappイメージからcont1という名前のコンテナが起動します。

コンテナ内では、CMDで指定したApacheが実行されます。

さらに、HEALTHCHECKで指定したコマンドが定期的に実行されます。

今回の設定では、10秒間隔で次のコマンドが実行されます。

curl -sf http://localhost/ || exit 1

このコマンドによって、ApacheがHTTPリクエストに正常に応答するかを確認します。

7. docker inspectでHEALTHCHECKの結果を確認する

参考資料では、docker inspectコマンドを使用してヘルスチェックの実行結果を確認しています。

次のコマンドを実行します。

docker inspect cont1

このコマンドでは、コンテナの詳細情報を取得できます。

取得した情報の中には、ヘルスチェックの実行結果も含まれます。

7-1. HealthのStatusを確認する

参考資料には、次のような出力例が掲載されています。

{
  "Health": {
    "Status": "healthy",
    "FailingStreak": 0,
    "Log": [
      {
        "Start": "2019-09-04T20:08:18.820425313+09:00",
        "End": "2019-09-04T20:08:19.245683023+09:00",
        "ExitCode": 0,
        "Output": "<h1>OK</h1>\n"
      }
    ]
  }
}

※これはdocker inspectの出力に含まれるHealth部分の抜粋です。

この例では、Statusがhealthyとなっています。

つまり、指定したヘルスチェックコマンドが成功している状態です。

7-2. Statusの意味

ヘルスチェックの状態は、主に次の値で表されます。

Status意味
startingヘルスチェックの初期状態
healthyヘルスチェックが成功している状態
unhealthyヘルスチェックが連続して失敗し、異常と判定された状態

コンテナを起動した直後は、まだヘルスチェックが完了していない場合があります。

その場合、Statusはstartingとして表示されることがあります。

その後、ヘルスチェックが成功するとhealthyになります。

一方、指定した回数だけ連続で失敗すると、unhealthyと判定されます。

7-3. FailingStreakとは

FailingStreakは、ヘルスチェックが連続して失敗した回数を表します。

参考資料の例では、次のようになっています。

"FailingStreak": 0

この場合、連続失敗回数は0回です。

--retries=3を設定した場合、通常は3回連続で失敗するとunhealthyになります。

7-4. ExitCodeとは

ExitCodeは、ヘルスチェックコマンドの終了コードを表します。

参考資料の例では、次のようになっています。

"ExitCode": 0

終了コードが0の場合、ヘルスチェックは成功と判定されます。

一方、失敗を示す終了コードが返された場合は、ヘルスチェックが失敗したものとして扱われます。

今回のDockerfileでは、curlが失敗した場合にexit 1を実行しています。

curl -sf http://localhost/ || exit 1

そのため、HTTPリクエストが失敗した場合は、ヘルスチェックも失敗として扱われます。

7-5. Outputとは

Outputには、ヘルスチェックコマンドの出力内容が記録されます。

参考資料の例では、次のようになっています。

"Output": "<h1>OK</h1>\n"

これは、Apacheが返したHTMLの内容です。

Dockerfileでは、次のようにHTMLファイルを作成しました。

RUN echo '<h1>OK</h1>' > /var/www/html/index.html

そのため、HTTPリクエストが成功すると、<h1>OK</h1>という内容が返されます。

このように、docker inspectでは、ヘルスチェックの状態だけでなく、実際に実行されたコマンドの結果も確認できます。

8. HEALTHCHECKの動作を整理する

今回の例では、Dockerfileに次のようなヘルスチェックを設定しました。

HEALTHCHECK --interval=10s --timeout=5s \
    CMD curl -sf http://localhost/ || exit 1

この設定によって、コンテナ起動後に次の処理が行われます。

  1. コンテナ内でApacheが起動する
  2. Dockerが指定した間隔でヘルスチェックコマンドを実行する
  3. curlでApacheにHTTPリクエストを送信する
  4. コマンドの終了結果をもとに成功・失敗を判定する
  5. ヘルスチェックの状態を記録する
  6. docker inspectで結果を確認できる

ヘルスチェックが成功している場合、Health.Statusはhealthyになります。

一方、失敗が指定回数に達した場合は、unhealthyになります。

9. HEALTHCHECKを使用するときの注意点

9-1. コンテナ内で実行できるコマンドを指定する

HEALTHCHECKに指定したコマンドは、コンテナ内で実行されます。

今回の例では、次のコマンドを使用しました。

curl -sf http://localhost/ || exit 1

そのため、コンテナ内でcurlコマンドを実行できる必要があります。

また、http://localhost/でアクセスできるように、Webサーバーが適切に設定されている必要があります。

9-2. ヘルスチェックの間隔を設定する

--intervalを使用すると、ヘルスチェックを実行する間隔を指定できます。

HEALTHCHECK --interval=10s \
    CMD curl -sf http://localhost/ || exit 1

実行間隔を短くすると、より頻繁に正常性を確認できます。

一方、ヘルスチェック自体もコマンドを実行する処理であるため、必要以上に短い間隔を設定しないよう注意が必要です。

9-3. タイムアウトと失敗回数を設定する

ヘルスチェックでは、タイムアウト時間と連続失敗回数も設定できます。

HEALTHCHECK --interval=10s --timeout=5s --retries=3 \
    CMD curl -sf http://localhost/ || exit 1

この設定では、ヘルスチェックが5秒以内に完了しない場合は失敗となります。

また、3回連続で失敗すると、コンテナはunhealthyと判定されます。

9-4. unhealthyはコンテナの停止を意味しない

HEALTHCHECKでunhealthyと判定されても、それだけでコンテナが自動的に停止・再起動されるわけではありません。

HEALTHCHECKは正常性を判定するための仕組みであり、コンテナの再起動処理そのものではないためです。

ヘルスチェックの状態とコンテナの実行状態は区別して考えましょう。

10. まとめ

今回は、DockerfileのHEALTHCHECK命令について解説しました。

HEALTHCHECKは、コンテナ内で定期的にコマンドを実行し、コンテナやアプリケーションの正常性を確認するための命令です。

例えば、次のように記述することで、WebサーバーへのHTTPリクエストを使用したヘルスチェックを設定できます。

HEALTHCHECK --interval=10s --timeout=5s --retries=3 \
    CMD curl -sf http://localhost/ || exit 1

今回のポイントは次のとおりです。

  • HEALTHCHECKはコンテナ内で定期的にコマンドを実行する
  • --intervalで実行間隔を指定できる
  • --timeoutでタイムアウト時間を指定できる
  • --retriesで異常判定までの連続失敗回数を指定できる
  • HTTPリクエストを使用してWebサーバーの応答を確認できる
  • docker inspectでヘルスチェックの状態を確認できる
  • Health.Statusがhealthyの場合は、設定したヘルスチェックが成功している
  • unhealthyは、必ずしもコンテナが停止したことを意味しない

DockerfileでWebサーバーなどのアプリケーションを構築する際は、コンテナの起動だけでなく、起動後の正常性をどのように確認するかも重要です。

まずは今回のDockerfileとdocker inspectを使って、ヘルスチェックの仕組みを理解してみましょう。


コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です