# 컨테이너가 unhealthy로 표시되나 서비스는 정상

> 컨테이너가 트래픽을 정상 처리하는데도 unhealthy로 보고됩니다 — 헬스 프로브 거짓 음성.

## 증상

컨테이너 — 보통 프런트엔드 — 가 `docker ps`에서 unhealthy로 표시되는데도, 애플리케이션은 브라우저에서 정상적으로 도달하고 서비스됩니다. 서비스가 작동 중인데도 헬스 프로브는 "connection refused"를 로깅합니다.

원인: 프로브가 `localhost`를 대상으로 하는데, 이는 IPv6(`::1`)와 IPv4(`127.0.0.1`)
**모두**로 해석됩니다. 프로브 도구는 IPv6를 먼저 시도하지만, 컨테이너 내부의 서버는
IPv4에서만 수신 대기하므로 — IPv6 시도가 거부되고 프로브가 컨테이너를 다운으로 잘못
보고합니다.

## 확인

컨테이너가 보고한 헬스 상태를 실제 도달 가능성과 비교해 확인하세요:

```bash
docker ps --format '{{.Names}}\t{{.Status}}' | grep aiboard
```

컨테이너가 `(unhealthy)`로 표시되는데 IPv4로 직접 접근했을 때 앱이 응답한다면, 이 거짓
음성입니다:

```bash
# 컨테이너 내부에서 — IPv4 명시
docker compose -f docker-compose.release.yml exec frontend \
  sh -c 'wget -qO- http://127.0.0.1:8080/ >/dev/null && echo "IPv4 OK"'
```

`IPv4 OK`가 출력되면 서비스는 정상이고 프로브만 잘못된 것입니다.

## 해결

현재 이미지는 이미 IPv4를 명시적으로 프로빙하므로 정상 박스에서는 이 문제가 발생하지
않습니다. 이전 이미지에서 이를 본다면:

1. **서비스가 실제로 작동 중인지 확인하세요**(위의 IPv4 검사가 `IPv4 OK`를 출력). 출력되면
   애플리케이션 측 조치는 필요 없습니다 — 컨테이너는 정상입니다.

2. **현재 릴리스 이미지로 업데이트하세요.** 여기서는 헬스 프로브가 `127.0.0.1`을 직접
   대상으로 하여 거짓 음성이 사라집니다:

   ```bash
   docker compose -f docker-compose.release.yml up -d
   ```

3. 상태가 해소되는지 **다시 확인**하세요:

   ```bash
   docker ps --format '{{.Names}}\t{{.Status}}' | grep aiboard
   ```

잘못된 것은 (서비스가 아니라) 프로브이므로, 이 컨테이너의 헬스를 기다리는 의존 컨테이너가
실제로는 모두 정상 서비스 중인데도 대기 상태에 머물 수 있습니다. 헬스체크를 비활성화하지
말고 프로브를 수정하세요.

## 예방

- **서버가 실제로 바인딩하는 주소를 프로빙하세요.** 서버가 IPv4에서만 수신 대기할 때는
  헬스 프로브가 `127.0.0.1`을 명시적으로 대상으로 해야, 이름 해석이 프로브를 바인딩되지
  않은 IPv6 주소로 보내지 않습니다.
- **프로브 실패와 서비스 실패를 구분하세요.** `unhealthy` 상태에 반응하기 전에 직접 IPv4
  요청으로 확인하세요. 빨간 프로브 뒤의 녹색 앱은 장애가 아니라 프로브 버그입니다.

## 관련 항목

- [관측성 및 알림](/operate/monitoring/) — 헬스 및 상태 신호 해석.
