DockerのHEALTHCHECKで死活監視して再起動をかける

やりたいこと

VPS上のDockerにのせたコンテナを死活監視して異常を検知したコンテナを再起動する
※1台構成の小規模な環境を想定
※ Docker version 20.10.6で検証

やりたいことを分けて以下の2つについて調べた
・HEALTHCHECK
・異常を検知でコンテナの再起動

HEALTHCHECK

Dockerの標準機能にコンテナが自身の状況をチェックする機能があるのでそれを使う
例えばWeb、MySQLコンテナをチェックしたい場合、testにチェック用の処理を記述して終了ステータス=1を返すと異常扱いとなる

他にもオプション(チェックの間隔、何秒後にチェックを開始するか、リトライ数など)があるのでドキュメントを参考

docker-composeの場合、ymlを設定してdocker-compose upで起動後、docker psコマンドの結果にSTATUShealthyまたはunhealthyが表示されるようになる

docker-compose.yml

web:
  container_name: web
  healthcheck:
    test: curl --fail http://web:8080/ || exit 1
・・・
db:
  container_name: db
  healthcheck:
    test: mysqladmin ping -uroot -p${MYSQL_ROOT_PASSWORD} || exit 1
・・・

docker psコマンドの結果

$ docker ps --format "table {{.Names}}\t{{.Status}}"
NAMES    STATUS
db       Up 9 minutes (healthy) ← 正常
web      Up 9 minutes (unhealthy) ← 異常

異常を検知でコンテナの再起動

HEALTHCHECKの結果によって自動でコンテナを再起動する機能はDocker標準ではないようなのでサードパーティ製のdocker-autohealイメージを利用する。
github.com

ドキュメントに書かれているとおりだが設定は簡単でdocker-compose.ymlに以下を追記するだけ

docker-compose.yml

autoheal:
  restart: always
  image: willfarrell/autoheal
  environment:
    - AUTOHEAL_CONTAINER_LABEL=all
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock

Dockerが管理しているHEALTHCHECKの結果を定期的に取得して、unhealthyであればコンテナを再起動する仕組みらしい。HEALTHCHECKが設定されていないコンテナは対象外となる。検証ではMySQLを無理やり落とすと一定時間後に自動で再起動されることが確認できた

docker psコマンドの結果

$ docker ps --format "table {{.Names}}\t{{.Status}}"
NAMES    STATUS
db       Up Less than a second (health: starting)
web      Up 9 minutes (unhealthy)

まとめ

・HEALTHCHECKはDocker標準機能を使う
・異常時の再起動はサードパーティのイメージを使う(または自前で実装する)