← 아티클 목록

도커 HEALTHCHECK — 컨테이너 상태를 제대로 관리하기

2026-10-19#docker#운영#헬스체크

docker ps에서 컨테이너가 Up이라고 떠도 그 안의 앱이 실제로 요청을 받을 수 있는 상태라는 보장은 없습니다. 프로세스는 떠 있지만 DB 연결이 끊겨 500만 뱉는 경우가 흔하죠. HEALTHCHECK는 컨테이너 안에서 주기적으로 명령을 실행해 "정말 정상인지"를 도커가 직접 판단하게 만듭니다.

1단계 — 현재 헬스 상태를 본다

로컬 터미널
# STATUS 컬럼에 (healthy)/(unhealthy) 표시
docker ps

# 헬스체크 실행 이력과 마지막 출력
docker inspect --format '{{json .State.Health}}' <container>

inspectHealth.Log에 최근 검사 결과와 명령 출력이 그대로 남아, unhealthy 원인을 바로 볼 수 있습니다.

2단계 — HEALTHCHECK 작성

Dockerfile
FROM node:20-slim
# ... 앱 빌드 ...
HEALTHCHECK --interval=10s --timeout=3s --start-period=30s --retries=3 \
  CMD curl -fsS http://localhost:3000/health || exit 1
CMD ["node", "dist/main.js"]

핵심 옵션은 정해져 있습니다.

옵션의미자주 틀리는 점
--interval검사 주기너무 짧으면 부하, 보통 10~30s
--timeout명령 제한 시간앱 응답보다 짧으면 오탐
--start-period기동 유예누락하면 시작 중에 unhealthy 처리
--retries연속 실패 허용1이면 일시적 끊김에도 unhealthy

--start-period를 빼먹으면 앱이 아직 뜨는 중인데 unhealthy로 찍혀, 오케스트레이터가 멀쩡한 컨테이너를 계속 죽입니다.

unhealthy 원인별 해결

  1. 헬스 엔드포인트가 없음/health 같은 경량 라우트를 앱에 추가합니다. 메인 페이지로 검사하면 DB 부하까지 끌고 옵니다.
  2. 이미지에 curl이 없음 — slim/alpine엔 curl이 없을 수 있습니다. wget -q -O- ... 또는 앱 자체 헬스 바이너리를 씁니다.
  3. timeout이 너무 짧음 — 콜드 스타트 응답이 timeout을 넘겨 오탐. timeout을 늘리거나 start-period를 줍니다.

Compose에서는 depends_oncondition: service_healthy로 의존 서비스가 healthy가 될 때까지 기동을 대기시킬 수 있습니다.

YAML
services:
  app:
    depends_on:
      db:
        condition: service_healthy

체크리스트

로컬 터미널
docker ps                                            # healthy 여부
docker inspect --format '{{json .State.Health}}' <c> # 실패 로그
docker exec <c> curl -fsS localhost:3000/health      # 안에서 직접 검사

컨테이너 안에서 직접 헬스 명령을 쳐 보면, 문제가 앱인지 헬스체크 설정인지 바로 갈립니다.


HEALTHCHECK를 붙여 일부러 unhealthy를 만들고 로그로 원인을 좁히는 실습은 도커 트랙에서 무료로 해볼 수 있습니다.