문제 발생

Compose를 실행하면 DB 컨테이너가 먼저 시작됐는데 web은 첫 연결에서 실패합니다. process가 시작된 시점과 실제 요청을 받을 준비가 끝난 시점은 다릅니다.

Compose의 시작 순서는 service가 요청을 처리할 준비가 됐음을 보장하지 않으므로 healthcheck와 application retry가 필요합니다.

원인 분석

짧은 depends_on은 dependency의 시작 순서를 표현하지만 application-level readiness까지 기다리지는 않습니다. service_healthy 조건을 쓰려면 dependency에 의미 있는 healthcheck가 있어야 합니다. 단순히 port가 열렸는지보다 실제로 필요한 최소 작업이 가능한지를 검사하되, 너무 많은 외부 dependency를 묶어 일시 장애마다 정상 컨테이너를 unhealthy로 만들지 않습니다.

해결 방안

DB가 연결을 받을 준비가 됐는지 healthcheck로 확인하고 web이 그 상태를 기다리게 합니다.

services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:18
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s
      timeout: 3s
      retries: 10
      start_period: 20s

Compose 밖의 재시작·network 흔들림도 있으므로 application 연결에는 총 deadline이 있는 제한 재시도를 둡니다. DB 준비 지연과 영구적인 비밀번호 오류를 구분해 후자는 빠르게 실패하게 합니다.

공식 문서

사용 중인 Compose version과 실제 healthcheck command의 권한·DB 이름을 확인합니다.