今回は Docker で使える「ヘルスチェック機能」を試す.Release Note を読むと,機能としては Docker 1.12 から使えるらしく,3年前からあったなんて...!仕組みとしては,Docker デーモンからコンテナに指定したコマンドを定期的に実行する.
Dockerfile 構文
「ヘルスチェック機能」を使う場合,まず Dockerfile
に HEALTHCHECK
を設定する.実行するコマンド以外に以下のオプションも設定できる.注意点として,--retries
以外は秒数を指定するため,表記は 5s
のように単位も付ける.
--interval=DURATION (default: 30s)
--timeout=DURATION (default: 30s)
--start-period=DURATION (default: 0s)
--retries=N (default: 3)
以下にサンプルを載せる.
HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/ || exit 1
検証用コンテナイメージ
今回は検証用コンテナイメージを「計3種類」作成した.Alpine を使うため,事前に curl
をインストールしておく必要がある.
kakakakakku/nginx:base
nginx:alpine
にcurl
を追加した
kakakakakku/nginx:ok
nginx:alpine
にcurl
とHEALTHCHECK
を追加した(ヘルスチェック成功)
kakakakakku/nginx:ng
nginx:alpine
にcurl
とHEALTHCHECK
を追加した(ヘルスチェック失敗)
Dockerfile : kakakakakku/nginx:ok
nginx を使うため,Dockerfile
に HEALTHCHECK
を設定し,curl
を実行する.今回は検証として,オプションは --interval=5s
と --timeout=3s
にした.kakakakakku/nginx:ok
は,デフォルトの index.html
にアクセスできるため,ヘルスチェックに成功する.
FROM nginx:alpine RUN apk add curl HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/ || exit 1
Dockerfile : kakakakakku/nginx:ng
kakakakakku/nginx:ng
は,誤った URL に curl
を実行するため「終了コード 1」となり,ヘルスチェックに失敗する.
FROM nginx:alpine RUN apk add curl HEALTHCHECK --interval=5s --timeout=3s CMD curl -f http://localhost/ng || exit 1
詳細は GitHub を見てもらえればと!
コンテナを起動する
コンテナを起動し,docker ps
コマンドを実行すると,以下のように STATUS
で「ヘルスチェック結果」を確認できる.通常は非表示だけど,今回は (healthy)
と (unhealthy)
が表示されている.なお,起動直後は (health: starting)
という表記になっていた.
$ docker run -d -p 8000:80 --name nginx01 kakakakakku/nginx:base $ docker run -d -p 8001:80 --name nginx02 kakakakakku/nginx:ok $ docker run -d -p 8002:80 --name nginx03 kakakakakku/nginx:ng $ docker ps --format "table {{.Image}}\t{{.Status}}\t{{.Names}}" IMAGE STATUS NAMES kakakakakku/nginx:ng Up 3 minutes (unhealthy) nginx03 kakakakakku/nginx:ok Up 3 minutes (healthy) nginx02 kakakakakku/nginx:base Up 3 minutes nginx01
コンテナの起動時にヘルスチェックを設定する
実は docker run
コマンドのオプションでヘルスチェックを指定することもできる.よって,Dockerfile
に HEALTHCHECK
が設定されていなくても「ヘルスチェック機能」は使える.オプションは以下のドキュメントに載っている.
--health-cmd
--health-interval
--health-retries
--health-start-period
--health-timeout
さっそく kakakakakku/nginx:base
を使って,「ヘルスチェックに成功するコンテナ」と「ヘルスチェックに失敗するコンテナ」を起動する.すると,Dockerfile
に HEALTHCHECK
を記載したときと同様に STATUS
に「ヘルスチェック結果」が表示された.オプションを柔軟に設定できるため,Dockerfile
にベタ書きするよりも使えそう.
$ docker run -d -p 8003:80 --name nginx04 \ --health-cmd 'curl -f http://localhost/ || exit 1' \ --health-interval 5s \ --health-timeout 3s \ kakakakakku/nginx:base $ docker run -d -p 8004:80 --name nginx05 \ --health-cmd 'curl -f http://localhost/ng || exit 1' \ --health-interval 5s \ --health-timeout 3s \ kakakakakku/nginx:base $ docker ps --format "table {{.Image}}\t{{.Status}}\t{{.Names}}" IMAGE STATUS NAMES kakakakakku/nginx:base Up 19 seconds (unhealthy) nginx05 kakakakakku/nginx:base Up 27 seconds (healthy) nginx04 kakakakakku/nginx:ng Up 11 minutes (unhealthy) nginx03 kakakakakku/nginx:ok Up 11 minutes (healthy) nginx02 kakakakakku/nginx:base Up 11 minutes nginx01
ヘルスチェック結果でフィルタリングする
docker ps
コマンドと --filter
を組み合わせることにより,ヘルスチェック結果でコンテナをフィルタリングすることもできる.
$ docker ps --format "table {{.Image}}\t{{.Status}}\t{{.Names}}" --filter 'health = healthy' IMAGE STATUS NAMES kakakakakku/nginx:base Up 2 minutes (healthy) nginx04 kakakakakku/nginx:ok Up 13 minutes (healthy) nginx02 $ docker ps --format "table {{.Image}}\t{{.Status}}\t{{.Names}}" --filter 'health = unhealthy' IMAGE STATUS NAMES kakakakakku/nginx:base Up 3 minutes (unhealthy) nginx05 kakakakakku/nginx:ng Up 14 minutes (unhealthy) nginx03
ヘルスチェックログを確認する
docker inspect
コマンドと --format
を組み合わせることにより,ヘルスチェックログ(直近5件)を確認できる.以下はヘルスチェックに失敗した nginx03
のログとなり,curl
の結果 404
で「終了コード 1」になっている(Output
の結果が長く,横スクロールをする必要がある).
$ docker inspect --format='{{json .State.Health}}' nginx03 | jq . { "Status": "unhealthy", "FailingStreak": 242, "Log": [ { "Start": "2019-11-21T06:22:46.3344018Z", "End": "2019-11-21T06:22:46.611824Z", "ExitCode": 1, "Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\ncurl: (22) The requested URL returned error: 404 Not Found\n" }, { "Start": "2019-11-21T06:22:51.622651Z", "End": "2019-11-21T06:22:51.8756001Z", "ExitCode": 1, "Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\ncurl: (22) The requested URL returned error: 404 Not Found\n" }, { "Start": "2019-11-21T06:22:56.8871398Z", "End": "2019-11-21T06:22:57.0339383Z", "ExitCode": 1, "Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\ncurl: (22) The requested URL returned error: 404 Not Found\n" }, { "Start": "2019-11-21T06:23:02.046402Z", "End": "2019-11-21T06:23:02.4194353Z", "ExitCode": 1, "Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\ncurl: (22) The requested URL returned error: 404 Not Found\n" }, { "Start": "2019-11-21T06:23:07.4317862Z", "End": "2019-11-21T06:23:07.6609581Z", "ExitCode": 1, "Output": " % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\ncurl: (22) The requested URL returned error: 404 Not Found\n" } ] }
ヘルスチェック結果の変化を検知する
docker events
コマンドと --filter
を組み合わせることにより,Docker のイベント情報から「ヘルスチェック結果の変化」を検知できる.以下は nginx05
コンテナを起動し,unhealthy
となったタイミングに取得したイベント情報となる.
$ docker events --filter 'type=container' --filter event=health_status 2019-11-21T15:44:18.141166300+09:00 container health_status: unhealthy xxxxx (image=kakakakakku/nginx:base, maintainer=NGINX Docker Maintainers <docker-maint@nginx.com>, name=nginx05)
まとめ
- Docker で使える「ヘルスチェック機能」を試した
Dockerfile
に設定することもできるし,docker run
コマンドのオプションに設定することもできる
docker ps
やdocker inspect
やdocker events
コマンドを使うと「ヘルスチェック」に関する情報を取得できる- 注意点として,Docker 単体だとヘルスチェックに失敗して
unhealthy
になったとしても,コンテナ自体はそのまま残る