Docker Compose のヘルスチェック設定完全ガイド|depends_on で起動順序を制御する実践チュートリアル

IT実務・技術メモ

マルチコンテナアプリケーションを Docker Compose で構築していると、「データベースの起動を待ってからアプリケーションサーバーを起動したい」という課題にぶつかることはありませんか。

単純に depends_on で依存関係を定義しても、コンテナが起動したことと、その中で実行されているサービスが準備完了したことは全く別です。データベースのプロセスが起動しているだけで、接続を受け付ける段階まで達していないのに、アプリケーションが接続を試みてしまい、エラーが発生することも多いです。

この記事では、Docker Compose のヘルスチェック機能と depends_on を組み合わせて、確実に起動順序を制御する実践的な方法を、ステップバイステップで解説します。

Docker Compose のヘルスチェックとは

ヘルスチェックは、コンテナ内で定期的に指定したコマンドを実行し、そのサービスが正常に動作しているかを判定する機能です。

従来の depends_on だけでは、コンテナのプロセスが起動したことしか確認できません。しかしヘルスチェックを組み合わせることで、サービスが実際に利用可能な状態になるまで待機できます。

ヘルスチェックの判定結果は以下の 4 つの状態を持ちます。

  • starting:コンテナ起動直後、ヘルスチェック開始前の状態
  • healthy:ヘルスチェックコマンドが成功した状態
  • unhealthy:ヘルスチェックコマンドが失敗した状態
  • none:ヘルスチェックが設定されていない状態

depends_on で起動順序を制御する従来の方法と限界

まず、従来の depends_on だけを使った設定を見てみます。

version: '3.8'

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: appdb

  app:
    image: myapp:latest
    depends_on:
      - db
    ports:
      - "8000:8000"

この設定では、app サービスは db サービスの起動後に起動が試みられます。しかし PostgreSQL のプロセスが起動しただけで、実際にクエリを受け付ける状態になるまでの数秒間は接続に失敗します。

その結果、アプリケーションが起動時に初期化クエリを実行しようとすると接続エラーが発生し、アプリケーション自体も起動に失敗してしまいます。

ヘルスチェック設定で サービスの準備完了を待機する

この問題を解決するには、ヘルスチェックを活用します。以下の例は PostgreSQL にヘルスチェックを設定したものです。

version: '3.8'

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: appdb
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

ヘルスチェックのパラメータについて説明します。

  • test:実行するコマンド。CMD または CMD-SHELL を指定
  • interval:ヘルスチェック間隔(秒単位)
  • timeout:コマンド実行のタイムアウト時間(秒単位)
  • retries:何回失敗したら unhealthy と判定するか
  • start_period:コンテナ起動から最初のヘルスチェック実行までの待機時間

上記の例では、PostgreSQL が起動してから 10 秒待機した後、5 秒ごとに pg_isready コマンドでポート接続可能性を確認します。

depends_on で condition: service_healthy を使う

Docker Compose 2.1 以降では、depends_oncondition パラメータを指定できます。これにより、単なる「起動」ではなく「ヘルスチェック成功」まで待機できます。

version: '3.8'

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: appdb
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

  app:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: "postgresql://admin:password@db:5432/appdb"

condition: service_healthy を指定することで、db サービスのヘルスチェックが成功するまで app の起動が待機されます。

複数サービス間の依存関係を設定する実例

より実践的な例として、データベース、キャッシュ、アプリケーションサーバーという 3 層構成を考えます。

version: '3.8'

services:
  db:
    image: postgres:15
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: password
      POSTGRES_DB: appdb
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s
    volumes:
      - db_data:/var/lib/postgresql/data

  cache:
    image: redis:7
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s
    depends_on:
      db:
        condition: service_healthy

  app:
    image: myapp:latest
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_healthy
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: "postgresql://admin:password@db:5432/appdb"
      REDIS_URL: "redis://cache:6379"

volumes:
  db_data:

このパターンでは以下の順序で起動が進みます。

  1. db サービスが起動し、ヘルスチェック成功を待機
  2. cache サービスが起動し、db が healthy になるまで待機
  3. cache のヘルスチェック成功後、app が起動
  4. appdbcache 両方が healthy になるまで待機

各サービスのヘルスチェック設定例

代表的なサービスのヘルスチェック設定パターンを紹介します。

PostgreSQL のヘルスチェック

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U admin -d appdb"]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 15s

MySQL のヘルスチェック

healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 10s
  timeout: 5s
  retries: 5
  start_period: 15s

Redis のヘルスチェック

healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 5s
  timeout: 3s
  retries: 3
  start_period: 5s

HTTP ベースのアプリケーションのヘルスチェック

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 30s

/health エンドポイントは、アプリケーションが起動後すぐに利用可能な軽量なチェックポイントです。

実践的なトラブルシューティング

ヘルスチェック設定時によくある問題と対策を紹介します。

ヘルスチェックコマンドが見つからない

pg_isreadyredis-cli などのツールがコンテナイメージに含まれていないと、ヘルスチェックが失敗します。Alpine ベースのイメージは特に注意が必要です。

解決方法は、Dockerfile で必要なツールをインストールするか、別のコマンドを使用することです。

FROM postgres:15-alpine
RUN apk add --no-cache postgresql-client

ヘルスチェック開始まで の待機時間が短すぎる

start_period を短く設定しすぎると、サービスがまだ初期化中にヘルスチェックが実行され、失敗判定されることがあります。

データベースマイグレーションなどが行われる場合は、十分な余裕を持たせましょう。

複雑な初期化処理がある場合

データベースマイグレーションやシード処理が必要な場合は、condition: service_healthy だけでは不十分な場合があります。

この場合は、待機スクリプトを使用するのが効果的です。pytest モック 使い方|外部API テスト を効率化する実践パターン5選

🤖 このブログはAIで自動運営しています。 同じ仕組みを御社にも導入できます。 無料相談はこちら
タイトルとURLをコピーしました