Docker には HEALTHCHECK というコンテナが正常稼働しているか確認する機能がある。
何をもって『正常』と判断するかはコンテナを稼働する人が指定する。Nginx みたいな Web サービスのコンテナの場合は公式サンプルにもある通りcurl
を死活監視のためのコマンドとして利用している。
curl -f http://localhost/ || exit 1
自コンテナの Web サーバからステータスコード 200 が返れば、シェルの終了コードも 0
になるので正常と判定されるし、ステータスコード 404 とかが返れば終了コードは 1 以上
となるので(curl の場合は 22
だった)exit 1
が実行されて終了コード 1
となり異常と判定される仕組み。
ヘルスチェック結果は docker ps
時に healthy
なのか unhealty
なのか表示される。
AWS の ECS でもこれを利用して『異常』の場合は既存のインスタンスを自動停止して新たなインスタンスに差し替えてくれたりする。
⛰ Alpine Linux の場合
wget
は最初から入ってるけど curl
は入ってない。別にいれればいいだけの話なんだけど、コンテナサイズを最小化することでしのぎを削ってる人達(?)からすれば耐え難いことかもしれない。大丈夫 wget
でも同じことができる。
🚝 Nginx を使ったテスト
お試し用の Dockerfile はこちら。
nginx:mainline-alpine
は Nginx 公式の Alpine Linux でつくられた最新安定版のコンテナ。
ビルドして起動すると curl
を指定しているため、コマンドが存在せず起動後に unhealthy
となる。
$ docker build -t nginx-health-check . $ docker run -it --rm nginx-health-check
起動直後
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7661b8c061fe nginx-health-check "nginx -g 'daemon of…" 4 seconds ago Up 2 seconds (health: starting) 80/tcp eager_lichterman
起動から 8 秒後
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7661b8c061fe nginx-health-check "nginx -g 'daemon of…" 10 seconds ago Up 8 seconds (unhealthy) 80/tcp eager_lichterman
🚀 wget に書き換える
wget -q -O - http://localhost/ || exit 1
にする。-q
は標準出力を出さない指定。-O -
はファイル出力先を - 指定することでなしにする。つまり標準出力にするという意味。
FROM nginx:mainline-alpine HEALTHCHECK --interval=5s --timeout=3s --start-period=5s --retries=1 \ CMD wget -q -O - http://localhost/ || exit 1 CMD ["nginx", "-g", "daemon off;"]
コンテナを改めてビルド
$ docker build -t nginx-health-check . $ docker run -it --rm nginx-health-check
今度は healthy
となる。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES feba790fbc78 nginx-health-check "nginx -g 'daemon of…" 6 seconds ago Up 5 seconds (healthy) 80/tcp distracted_chandrasekhar