尋常でないもふもふ

a software engineer blog

DockerのHEALTHCHECKをwgetでやる

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 はこちら。

gist.github.com

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