エラーの概要

Docker Compose の 500 エラーは、Docker Compose 自体またはそれが管理するコンテナー内で内部エラーが発生したことを示します。このエラーは通常、コンテナー起動時のアプリケーションクラッシュ、エントリポイント実行の失敗、またはヘルスチェック機構の不具合によって引き起こされます。対象のサービスが正常に起動・稼働できない状態を意味しており、迅速な原因特定と対応が必要です。

実際のエラーメッセージ例

Docker Compose でコンテナーが起動に失敗した際の典型的なエラー出力は以下の通りです。

ERROR: for <service-name>  Cannot start service <service-name>: 
OCI runtime create failed: container_linux.go:380: 
starting container process caused: exec: 
"<command>": executable file not found in $PATH: unknown

または、ヘルスチェック失敗時は以下のように表示されます。

<service-name> | ERROR: Health check failed. Retrying...
<service-name> | (Exit status: 1)

アプリケーション実行時のエラーログは以下のようなパターンです。

docker-compose logs <service-name>
<service-name> | Traceback (most recent call last):
<service-name> |   File "/app/main.py", line 15, in <module>
<service-name> |     raise Exception("Database connection failed")
<service-name> | Exception: Database connection failed

よくある原因と解決手順

原因1:サービスのコンテナー内部でアプリケーションがクラッシュしている

コンテナー起動後、アプリケーションが異常終了またはランタイムエラーで落ちてしまう状況です。これは依存関係の欠落、設定ファイルの不在、メモリ不足、または不正な初期化処理によって発生します。

Before(エラーが起きるコード):

version: '3.8'
services:
  app:
    image: python:3.9
    working_dir: /app
    command: python main.py
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb

上記の場合、main.pyDATABASE_URL をパースしようとした際に例外が発生したり、必要なライブラリがインストールされていない場合にクラッシュします。

After(修正後):

version: '3.8'
services:
  app:
    build: .
    working_dir: /app
    command: python main.py
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    depends_on:
      db:
        condition: service_healthy
    restart: on-failure

対応する Dockerfile では依存パッケージをすべてインストールし、エラーハンドリングを強化します。

FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "main.py"]

診断コマンド:

docker compose logs <service-name>

このコマンドでアプリケーション側のスタックトレースや例外メッセージが表示されます。メッセージから原因を特定し、コード修正またはパッケージインストールを行います。

原因2:コンテナーのエントリポイントやコマンドが失敗して終了した

docker-compose.ymlcommand または entrypoint に指定したスクリプト・実行ファイルが見つからない、または実行権限がない場合に発生します。これはパス指定の誤り、ファイルの忘れ、ビルド時のレイヤー構成ミスが原因となります。

Before(エラーが起きるコード):

version: '3.8'
services:
  web:
    image: nginx:latest
    entrypoint: /app/start.sh
    ports:
      - "80:80"

start.sh がイメージ内に存在しないか、実行権限がない状態です。

After(修正後):

version: '3.8'
services:
  web:
    build: .
    entrypoint: ["/bin/sh", "-c"]
    command: "chmod +x /app/start.sh && /app/start.sh"
    ports:
      - "80:80"

対応する Dockerfile

FROM nginx:latest
COPY start.sh /app/start.sh
RUN chmod +x /app/start.sh
EXPOSE 80

診断コマンド:

docker compose ps

コンテナーの状態が Exit (1) または類似のステータスになっていれば、エントリポイント実行時の失敗です。

docker compose logs <service-name>

で詳細なエラーメッセージを確認します。

原因3:ヘルスチェックが失敗しコンテナーが再起動ループに入っている

healthcheck で定義されたチェックが継続的に失敗し、Docker がコンテナーを繰り返し再起動するため、サービスが安定しない状態です。これはアプリケーション起動時間がタイムアウト値より長い、ポート待機が遅い、または接続情報が誤っている場合に発生します。

Before(エラーが起きるコード):

version: '3.8'
services:
  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 5s
      timeout: 1s
      retries: 3

アプリケーション起動に 10 秒必要な場合、タイムアウト値 1s と再試行回数 3 回では十分な時間がなく、何度も再起動が繰り返されます。

After(修正後):

version: '3.8'
services:
  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s

start_period を追加することで、コンテナー起動直後のヘルスチェックを遅延させ、アプリケーションが準備完了するまで待機します。

診断コマンド:

docker compose logs <service-name> --tail=50

繰り返されるエラーメッセージを確認し、ヘルスチェック失敗の理由を特定します。

docker inspect <container-id> | grep -A 20 "Health"

現在のヘルスチェック状態を詳細に表示します。

ツール固有の注意点

サービス間の依存関係と起動順序

Docker Compose の depends_on オプションはデフォルトではサービスの起動完了を待たず、コンテナー起動後すぐに次のサービスを起動します。データベースが完全に初期化される前にアプリケーションが接続を試みる場合、500 エラーが発生します。

version: '3.8'
services:
  app:
    depends_on:
      db:
        condition: service_healthy
  db:
    healthcheck:
      test: ["CMD", "pg_isready"]

condition: service_healthy を使用することで、ヘルスチェック成功までアプリケーション起動を遅延させます。

マルチステージビルドでの依存関係漏れ

Dockerfile でマルチステージビルドを使用する場合、最終ステージに必要なランタイムやライブラリをコピーし忘れると、実行時に 500 エラーが発生します。

FROM golang:1.19 as builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:latest
COPY --from=builder /app/myapp /usr/local/bin/
# libc がないため実行時エラー

解決策として、必要なライブラリをインストールします。

FROM alpine:latest
RUN apk add --no-cache libc6-compat
COPY --from=builder /app/myapp /usr/local/bin/

環境変数の未設定

アプリケーションが必須環境変数を参照しているが、docker-compose.yml で定義されていない場合、初期化時に例外が発生します。

docker compose config

で設定全体を確認し、環境変数が適切に展開されているか検査します。

それでも解決しない場合

詳細なログ確認

docker compose logs <service-name> -f --tail=100

-f フラグでリアルタイムログを監視し、--tail=100 で直近 100 行を表示します。

個別サービスの起動テスト:

docker compose up --no-deps -d <service-name>
docker compose logs <service-name>
docker compose down

このコマンドセットでサービスを独立起動し、他のサービスの影響を除外して原因を特定できます。

コンテナー内での直接実行

docker compose run --rm <service-name> /bin/bash

でコンテナー内のシェルを取得し、手動でアプリケーションを実行してエラーを確認します。

イベントログの確認

docker events --filter type=container

でコンテナーのライフサイクルイベント(起動、停止、再起動)を監視します。

公式ドキュメント参照


免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。