Quick Comparison
HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=10s \
CMD curl -f http://localhost:3000/health || exit 1# 헬스 상태 확인
docker inspect --format='{{.State.Health.Status}}' my-apprunning은 프로세스 상태이고, healthy는 컨테이너 안에서 실행한 검사 결과입니다. healthcheck가 unhealthy가 되어도 Docker가 컨테이너를 자동으로 재시작하지 않으므로, 재기동과 의존 서비스 처리는 별도로 설계합니다.
readiness 상태
running 상태와 healthy 상태가 왜 다른가
컨테이너가 running 상태여도 앱이 요청을 받을 준비가 됐다는 보장은 없다. 프로세스는 시작됐지만 DB 연결을 맺는 중이거나, 캐시를 로딩하는 중일 수 있다. HEALTHCHECK는 주기적으로 검사 명령을 실행해 healthy / unhealthy 상태를 별도로 추적한다.
# 상태 전이 흐름
# starting → healthy (검사가 한 번 성공)
# starting → unhealthy (retries 초과 실패)
# healthy → unhealthy (이후 검사에서 retries 초과 실패)
docker inspect --format='{{json .State.Health}}' my-appinterval, timeout, retries, start-period 파라미터가 결정하는 것
각 파라미터는 검사의 타이밍과 내성(tolerance)을 조정한다. interval은 검사 주기, timeout은 검사 명령 최대 허용 시간, retries는 unhealthy로 전환하기까지 실패 허용 횟수, start-period는 컨테이너 시작 직후 실패를 카운트하지 않는 유예 시간이다. start period 안에 한 번 성공하면 그 뒤 실패는 바로 retries에 포함된다.
HEALTHCHECK \
--interval=15s \ # 15초마다 검사
--timeout=5s \ # 검사가 5초 초과하면 실패로 간주
--retries=5 \ # 5회 연속 실패해야 unhealthy 전환
--start-period=30s \ # 시작 후 30초간 실패는 카운트 안 함
CMD wget -qO- http://localhost:8080/ready || exit 1의존 서비스 시작 조건
Compose의 depends_on: condition: service_healthy와 연동하는 방법
Compose에서 의존 서비스가 healthy 상태가 된 뒤에 다른 서비스를 시작하고 싶을 때 사용한다. depends_on만 쓰면 컨테이너 시작 순서만 보장하고 준비 여부는 무시한다. condition: service_healthy를 추가해야 실제로 준비된 뒤 다음 서비스가 올라온다.
services:
db:
image: postgres:17
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
api:
build: .
depends_on:
db:
condition: service_healthy # db가 healthy 상태가 된 후 시작검사 설계와 운영 경계
포트 열림 검사와 앱 레벨 readiness 검사는 의미가 다르다
TCP 포트가 열려 있다는 것은 프로세스가 리슨 중이라는 뜻일 뿐이고, 실제로 앱이 DB 연결이나 캐시 초기화를 끝냈다는 뜻은 아닙니다. 운영 카드에서는 nc -z localhost 3000 같은 단순 포트 검사보다 /health, pg_isready, redis-cli ping처럼 앱 또는 의존 서비스 의미를 반영하는 검사가 더 신뢰할 만합니다. /health가 무엇을 검사하는지는 애플리케이션 계약이므로, readiness와 liveness를 같은 endpoint에 둘지 명시합니다.
CMD와 CMD-SHELL 선택
test: ["CMD", "curl", "-f", "http://localhost"]는 셸을 거치지 않고 실행합니다. 파이프, ||, 환경 변수 확장처럼 셸 문법이 필요하면 CMD-SHELL 또는 문자열 형태를 사용합니다. 검사 명령의 shell 의존성을 숨기지 않아야 이미지가 바뀌어도 실패 원인을 읽을 수 있습니다.
검사 파라미터 선택
| 상황 | 적합한 선택 |
|---|---|
| 앱 초기화 시간이 긴 서비스 | --start-period를 충분히 설정 |
| 의존 서비스 준비 후 시작 보장 | depends_on: condition: service_healthy |
| 검사 명령이 무거울 때 | --interval 늘려 검사 빈도 줄이기 |
| DB readiness 확인 | pg_isready, mysqladmin ping 사용 |
| HTTP 서비스 readiness 확인 | /health 엔드포인트에 curl -f |
unhealthy 이후의 대응
healthcheck는 상태를 기록할 뿐 컨테이너를 재시작하지 않습니다. unhealthy 뒤에 무엇을 할지는 Compose 의존성, Docker restart policy, 오케스트레이터, 외부 monitor 중 누가 책임지는지 정해야 합니다. 앱 레벨 endpoint도 실제로 DB 연결·migration까지 보장하는지는 해당 endpoint의 계약에 따라 확인합니다.
참고 링크
2 sources