エラーの概要
503エラーは「Service Unavailable」を意味し、Docker Composeでは依存するサービスが正常に起動できていない、または起動完了前にアクセスされている状況を示します。マイクロサービスアーキテクチャではよく発生するエラーで、特に複数コンテナーの起動順序やヘルスチェック設定に起因することが多いです。
実際のエラーメッセージ例
Docker Composeで503エラーが発生した際のログ例を以下に示します。
{
"status": 503,
"message": "Service Unavailable",
"error": "connect ECONNREFUSED 172.20.0.3:5432"
}
docker compose logs app-service
2024-01-15T10:23:45.123Z ERROR Failed to connect to database: ECONNREFUSED
2024-01-15T10:23:46.456Z WARN Service startup failed, retrying...
2024-01-15T10:23:50.789Z ERROR Max retries exceeded
よくある原因と解決手順
原因1:depends_onで依存関係を定義しているが、ヘルスチェック待機を設定していない
マイクロサービス構成では、アプリケーションコンテナーがデータベースコンテナーの完全な起動完了を待つ必要があります。docker compose up実行時、デフォルトでは依存するコンテナーが「起動した」ことだけを確認して先に進むため、データベースが受け入れ準備完了する前にアクセスされます。
Before(エラーが起きるコード):
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
app:
image: myapp:latest
depends_on:
- postgres
ports:
- "8080:8080"
After(修正後):
version: '3.8'
services:
postgres:
image: postgres:15
environment:
POSTGRES_PASSWORD: password
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
app:
image: myapp:latest
depends_on:
postgres:
condition: service_healthy
ports:
- "8080:8080"
上記の修正では、service_healthy条件によってPostgresのヘルスチェック成功を待ってからアプリケーション起動が開始されます。
原因2:ヘルスチェックコマンドが不適切で常に失敗している
ヘルスチェックが定義されていても、そのコマンドが実装されていない、不正な形式、または環境に合わない場合、サービスは「unhealthy」と判定され続け、503エラーが解決されません。
Before(エラーが起きるコード):
version: '3.8'
services:
redis:
image: redis:7
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:6379/health"]
interval: 5s
retries: 3
After(修正後):
version: '3.8'
services:
redis:
image: redis:7
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
app:
image: myapp:latest
depends_on:
redis:
condition: service_healthy
environment:
REDIS_HOST: redis
REDIS_PORT: 6379
Redisの場合、redis-cli pingがヘルスチェック手段として有効です。対象サービスに応じて適切なコマンドを選択してください。
原因3:コンテナーが起動直後に停止している(エントリーポイントエラー)
アプリケーションコンテナーが起動スクリプトや依存パッケージの不足でクラッシュしている場合、Docker Composeがサービスを「起動した」と判定しても実際には停止状態になり、503エラーが返されます。
Before(エラーが起きるコード):
FROM python:3.11
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# アプリケーション起動時にエラーが発生する可能性
CMD ["python", "app.py"]
After(修正後):
FROM python:3.11
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# ヘルスチェックエンドポイントを公開
EXPOSE 8080
# エラーハンドリングと起動ログの追加
CMD ["sh", "-c", "echo 'Starting app...' && python app.py || (echo 'App startup failed'; exit 1)"]
同時にDocker Composeの設定でも確認メカニズムを追加します。
version: '3.8'
services:
app:
build: .
container_name: myapp
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 10s
timeout: 5s
retries: 3
start_period: 15s
restart: on-failure
ツール固有の注意点
Docker Composeで503エラーを防ぐために、以下のベストプラクティスに従うことが重要です。
ヘルスチェックのstart_periodパラメーター:アプリケーション初期化に時間がかかる場合は、start_periodを設定して初期ヘルスチェック失敗を無視させます。これにより、起動直後の一時的な接続失敗で「unhealthy」と判定されるのを防げます。
複数レイヤーの依存構成:3層以上のマイクロサービス構成(例:Nginx → API → Database)では、各層すべてにcondition: service_healthyを設定します。中間層のみ待機しても、その先のサービスがダウンしていれば結局503エラーが発生します。
ネットワーク分離:複数のCompose設定を運用する場合、networksセクションで明示的にネットワークを定義し、不要なサービス間通信を遮断することで、予期しない503エラーの原因を減らせます。
version: '3.8'
services:
postgres:
image: postgres:15
networks:
- backend
app:
image: myapp:latest
networks:
- backend
depends_on:
postgres:
condition: service_healthy
networks:
backend:
driver: bridge
それでも解決しない場合
503エラーが継続する場合は、以下の手順で詳細な原因調査を行います。
ログ確認コマンド:
# 全サービスのログを時系列で表示
docker compose logs -f
# 特定サービスのみ確認
docker compose logs -f postgres
# 起動失敗の詳細メッセージを確認
docker compose logs app-service | grep -i error
コンテナー状態の確認:
# 全コンテナーの状態を表示
docker compose ps
# 特定コンテナーの詳細情報
docker inspect <container_id>
# ヘルスチェック状態の確認
docker compose exec postgres pg_isready -U postgres
ネットワーク疎通確認:
# 別コンテナーから対象サービスへの接続テスト
docker compose exec app curl -v http://postgres:5432
# ポートリッスン状態の確認
docker compose exec postgres netstat -tlnp
設定ファイルの検証:
# compose.ymlの構文エラーを確認
docker compose config --quiet
# 明示的なエラーメッセージ表示
docker compose config
Composeファイルに記述エラーがないか、公式ドキュメント(https://docs.docker.com/compose/compose-file/)で仕様を再確認し、特にcondition値がservice_healthy、service_started、service_completed_successfullyのいずれかか確認してください。
免責事項:本記事の内容は、執筆時点の公開情報をもとに作成したものです。ソフトウェアの仕様は予告なく変更されることがあります。最新の情報は各ツールの公式サポートページをご確認ください。本記事の情報を利用した結果生じたいかなる損害についても、著者および運営者は責任を負いかねます。