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、または自前の仕組みで対処する

関連記事:

お気軽にご相談ください

お見積りへ お問い合わせへ
▲