2026年5月31日
2026年5月31日
Dockerのヘルスチェックを設定する方法|HEALTHCHECK・Compose・docker run
Docker のヘルスチェックは、コンテナの中で決まったコマンドを定期的に実行し、その結果からコンテナが「正常に応答しているか」を判定する仕組みです。プロセスが動いていても、Web サーバーがエラーを返している、データベースがまだ接続を受け付けていない、といった状態を見分けられます。
この記事では、ヘルスチェックを Dockerfile・Docker Compose・docker run の3通りで設定する方法と、結果の確かめ方を説明します。動作は 2026年10月時点の Docker Engine 29、Docker Compose v5、nginx:1.28 と mariadb:11 のイメージで確認しています。
ヘルスチェックの仕組み
ヘルスチェックを設定したコンテナは、次の3つの状態のどれかになります。
| 状態 | 意味 |
|---|---|
starting |
起動直後。まだ判定が出ていない |
healthy |
チェックのコマンドが成功(終了コード 0)した |
unhealthy |
チェックのコマンドが、決められた回数続けて失敗した |
チェックのコマンドは、終了コード 0 で成功、1 で失敗を表します(2 は予約されているので使いません)。
注意: Docker Engine 単体では、コンテナが unhealthy になっても自動で再起動はされません。--restart の再起動ポリシーは、コンテナのプロセスが終了したときにだけ働きます。対処は後半の「unhealthyになっても再起動されない」で説明します。
Dockerfileで設定する
Dockerfile に HEALTHCHECK 命令を書くと、そのイメージから作るコンテナすべてにヘルスチェックが付きます。
FROM nginx:1.28
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --start-interval=2s --retries=3 \
CMD curl -fsS -o /dev/null http://localhost/ || exit 1
curl の -f は、HTTP のステータスが 400 以上のときに終了コード 22 で終わらせるオプションです。|| exit 1 で、失敗をすべて終了コード 1 にそろえています。
| オプション | 初期値 | 意味 |
|---|---|---|
--interval |
30s |
チェックの間隔 |
--timeout |
30s |
1回のチェックにかける時間の上限。超えると失敗 |
--start-period |
0s |
起動直後の猶予期間。この間の失敗は回数に数えない(成功すればその時点で healthy) |
--start-interval |
5s |
猶予期間中のチェックの間隔(Docker Engine 25.0 以降) |
--retries |
3 |
何回続けて失敗したら unhealthy にするか |
--start-interval を付けないと、最初のチェックは起動から --interval の時間がたってから行われるので、healthy になるまで30秒ほど starting のままです。
ベースイメージにヘルスチェックが設定されていて、それを止めたい場合は HEALTHCHECK NONE と書きます。
チェックに使うコマンドがイメージにあるか確かめる
チェックのコマンドはコンテナの中で実行されるので、そのコマンドがイメージに入っている必要があります。公式の nginx イメージには curl が入っていますが、curl も wget も入っていないイメージは多くあります。事前に確かめておきます。
docker run --rm nginx:1.28 sh -c 'command -v curl wget'
何も表示されなければ、どちらも入っていません。その場合は、Dockerfile でインストールするか、アプリ自身が持っている確認用のコマンドを使います(例:公式の mariadb イメージの healthcheck.sh)。
Docker Composeで設定する
Compose ファイル(compose.yaml)では、サービスごとに healthcheck を書きます。
services:
db:
image: mariadb:11
environment:
MARIADB_ROOT_PASSWORD: example
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
start_interval: 2s
web:
image: nginx:1.28
ports:
- "8080:80"
healthcheck:
test: ["CMD-SHELL", "curl -fsS -o /dev/null http://localhost/ || exit 1"]
interval: 30s
timeout: 5s
retries: 3
depends_on:
db:
condition: service_healthy
testの先頭がCMDなら、続く要素をそのままコマンドとして実行します。CMD-SHELLなら、続く文字列をシェル(/bin/sh -c)で実行するので、||などが使えますdepends_onにcondition: service_healthyを付けると、dbがhealthyになってからwebを起動します。データベースの準備ができる前にアプリが起動して接続エラーになる、という問題を防げます- イメージに設定されたヘルスチェックを止めるには、
healthcheck:の下にdisable: trueと書きます
起動すると、db が Healthy になるのを待ってから web が起動する様子が表示されます。
docker compose up -d
Container hc-db-1 Started
Container hc-db-1 Waiting
Container hc-db-1 Healthy
Container hc-web-1 Starting
Container hc-web-1 Started
Compose ファイルの先頭に version: '3.8' のような行を書く必要はありません。現在の Docker Compose では使われず、書くと「obsolete(廃止)」の警告が出ます。
docker runで設定する
イメージを作り直さずに、コンテナを作るときにヘルスチェックを付けることもできます。
docker run -d --name my-nginx \
--health-cmd='curl -fsS -o /dev/null http://localhost/ || exit 1' \
--health-interval=30s \
--health-timeout=5s \
--health-retries=3 \
--health-start-period=10s \
nginx:1.28
--health-cmd はシェルで実行されます。イメージに設定されたヘルスチェックを止めるには --no-healthcheck を付けます。
ヘルスチェックの設定は、コンテナを作るときに決まります。すでに動いているコンテナに後から付けることはできないので、変えたいときはコンテナを作り直します。
状態を確かめる
docker ps の STATUS に、ヘルスチェックの状態が表示されます。
docker ps --format '{{.Names}} {{.Status}}'
my-nginx Up 5 seconds (healthy)
詳しい結果は docker inspect で見られます。
# 状態だけ
docker inspect --format '{{.State.Health.Status}}' my-nginx
# 直近のチェックの終了コードと出力
docker inspect --format '{{json .State.Health}}' my-nginx
{"Status":"healthy","FailingStreak":0,"Log":[{"Start":"2026-10-29T17:39:31.069523955Z","End":"2026-10-29T17:39:31.146682497Z","ExitCode":0,"Output":""}]}
FailingStreak は続けて失敗した回数、Log の ExitCode と Output はチェックのコマンドの終了コードと出力です。unhealthy になったときは、Output に失敗の理由が残ります。終了コードと出力だけを並べて表示するには次のようにします。
docker inspect --format '{{range .State.Health.Log}}{{.ExitCode}} {{.Output}}{{end}}' my-nginx
1 curl: (22) The requested URL returned error: 403
unhealthy のコンテナだけを一覧にしたり、状態が変わったときのイベントを見たりすることもできます。
# unhealthy のコンテナだけを表示
docker ps --filter health=unhealthy
# ヘルスチェックの状態の変化を表示し続ける(Ctrl+C で終了)
docker events --filter event=health_status
unhealthyになっても再起動されない
検証では、--restart unless-stopped を付けたコンテナが unhealthy になっても、再起動の回数(RestartCount)は 0 のままでした。Docker Engine 単体では、ヘルスチェックの結果で再起動は行われません。
unhealthy のときに再起動させたい場合は、次のような方法があります。
- Docker Swarm のサービスとして動かす:Swarm モードでは、
unhealthyになったタスク(コンテナ)は停止され、新しいものに置き換えられます - Kubernetes を使う:liveness probe が失敗したコンテナは再起動されます
- 自分で再起動する:
unhealthyのコンテナを探して再起動するコマンドを cron などで定期的に実行します
# unhealthy のコンテナをすべて再起動する
docker ps -q --filter health=unhealthy | xargs -r docker restart
再起動で直るのは一時的な不具合だけです。何度も unhealthy になる場合は、docker inspect の Output やコンテナのログ(docker logs)で原因を調べます。
設定するときの注意点
- チェックは軽くする:チェックは間隔ごとにコンテナの中で実行されます。重い処理(データベースへの大きな問い合わせなど)は避け、応答を返すだけの確認用のページやコマンドを使います
- 外部のサービスに依存させない:外部の API などをチェックに含めると、そのサービスの障害で自分のコンテナまで
unhealthyになります --timeoutと--start-periodを実際の動きに合わせる:起動に時間がかかるアプリでは、--start-periodを短くしすぎると起動途中の失敗が数えられ、unhealthyになりますlocalhostで確認する:チェックはコンテナの中で動くので、ホストのポート(例:8080)ではなく、コンテナの中で待ち受けているポートに接続します
まとめ
- ヘルスチェックはコンテナの中でコマンドを定期的に実行し、終了コード 0 なら
healthy、続けて失敗するとunhealthyにする - 設定は Dockerfile の
HEALTHCHECK、Compose のhealthcheck、docker runの--health-*のどれでもできる --start-periodと--start-intervalで、起動直後の判定を調整できる- Compose の
depends_onとcondition: service_healthyで、依存するサービスの準備ができてから起動できる - Docker Engine 単体では
unhealthyでも再起動されない。Swarm、Kubernetes、または自前の仕組みで対処する
関連記事: