개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Docker Health Check — 컨테이너 상태를 모니터링하는 방법

2025년 7월 6일
DockerHealth CheckHEALTHCHECKhealthyunhealthy

컨테이너가 실행 중이라고 해서 서비스가 정상이라는 보장은 없다. 프로세스는 살아있지만 데이터베이스 연결이 끊겼거나, HTTP 엔드포인트가 500을 반환하는 상황이 실제로 발생한다. Docker Health Check는 이런 상황을 감지해 컨테이너 상태를 healthy / unhealthy로 분류한다.

HEALTHCHECK 명령어

Dockerfile에 HEALTHCHECK 명령어를 추가하면 Docker 데몬이 주기적으로 해당 명령을 실행해 컨테이너 상태를 판단한다.

FROM node:20-alpine

WORKDIR /app
COPY . .
RUN npm ci --omit=dev

HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
  CMD wget -qO- http://localhost:3000/health || exit 1

CMD ["node", "server.js"]

--interval: 헬스 체크 실행 간격 (기본값 30s) / --timeout: 명령 타임아웃 (기본값 30s) / --start-period: 컨테이너 시작 후 첫 체크까지 대기 시간 (기본값 0s) / --retries: 연속 실패 횟수가 이 값을 넘으면 unhealthy 처리 (기본값 3)

헬스 체크 명령의 종료 코드가 0이면 healthy, 1이면 unhealthy로 판단한다. 2는 예약된 값으로 사용하지 않는다.

상태 전이 흐름

컨테이너 시작
     │
     ▼
 [starting]  ◄─── start-period 동안 실패해도 무시
     │
     │  start-period 경과 후 첫 성공
     ▼
  [healthy]
     │
     │  retries 횟수 연속 실패
     ▼
 [unhealthy]
     │
     │  다시 성공
     ▼
  [healthy]

starting 상태는 컨테이너가 초기화되는 동안 불필요한 경보를 막기 위해 존재한다. --start-period를 애플리케이션 부팅 시간보다 충분히 크게 설정해야 한다.

docker inspect로 상태 확인

docker inspect --format='{{json .State.Health}}' <container_id> | jq

출력 예시:

{
  "Status": "healthy",
  "FailingStreak": 0,
  "Log": [
    {
      "Start": "2027-01-18T09:00:00Z",
      "End": "2027-01-18T09:00:00.123Z",
      "ExitCode": 0,
      "Output": "OK"
    }
  ]
}

Log 배열에는 최근 5개의 체크 결과가 저장된다. ExitCode와 Output으로 실패 원인을 빠르게 파악할 수 있다.

docker run에서 옵션 오버라이드

이미지에 HEALTHCHECK가 없거나 값을 재정의하고 싶을 때는 docker run 플래그를 사용한다.

docker run \
  --health-cmd="curl -f http://localhost:8080/ping || exit 1" \
  --health-interval=15s \
  --health-timeout=3s \
  --health-retries=2 \
  my-image

반대로 이미지에 정의된 헬스 체크를 비활성화하려면 --no-healthcheck 플래그를 사용한다.

옵션 비교

옵션기본값권장 범위설명
--interval30s10s–60s체크 실행 주기
--timeout30s2s–10s단일 명령 타임아웃
--start-period0s앱 부팅 시간 이상초기화 유예 기간
--retries32–5unhealthy 판정 연속 실패 횟수

--timeout이 --interval보다 크면 의미가 없다. 타임아웃은 항상 인터벌보다 짧게 설정한다.

/health 엔드포인트 설계

헬스 체크 명령이 호출하는 엔드포인트는 단순해야 한다. 외부 의존성(DB, 캐시 등) 확인을 포함할 경우, 해당 의존성 장애가 컨테이너 재시작을 유발한다는 점을 의도적으로 선택해야 한다.

// Express 예시
app.get('/health', (_req, res) => {
  res.status(200).json({ status: 'ok' });
});

의존성 확인이 필요하다면 /health/live(프로세스 생존)와 /health/ready(트래픽 수용 가능)를 분리하는 패턴이 Kubernetes의 livenessProbe / readinessProbe와도 자연스럽게 맞는다.

← 이전 글Docker 환경 변수 — 컨테이너에 설정값을 전달하는 방법
다음 글 →Docker Logging — 컨테이너 로그를 수집하는 방법