이전 글에서 Thread.sleep(300000)으로 5분을 기다리던 구조를 개선해야겠다고 정리했습니다.
이번에는 실제로 Docker Health Check를 이용해서 준비 상태를 확인하는 방식으로 바꾼 내용을 정리해보겠습니다.
핵심은 이겁니다.
“컨테이너가 떠 있는지”가 아니라
“애플리케이션이 정상 상태인지”를 확인하자.
1. Dockerfile에 HEALTHCHECK 정의하기
먼저 전제가 하나 필요합니다.
컨테이너에 HEALTHCHECK가 정의되어 있어야 합니다.
예를 들어 Spring Boot라면:
HEALTHCHECK --interval=30s --timeout=5s --retries=5 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
- 30초 간격으로 체크
- 5초 타임아웃
- 5번 실패하면 unhealthy
이 설정이 있어야 Docker가 내부적으로 healthy / unhealthy 상태를 관리합니다.
2. 현재 Health 상태 확인 명령어
Docker에서 상태를 확인하는 명령어는 다음입니다.
docker inspect -f '{{.State.Health.Status}}' container_name
결과는 보통 다음 중 하나입니다.
- starting
- healthy
- unhealthy
이 값을 Java에서 SSH로 받아서 판단하면 됩니다.
3. Java에서 Health 상태 대기 로직 구현
기존에는:
Thread.sleep(300000);
이렇게 무조건 5분을 기다렸습니다.
이제는 아래와 같은 방식으로 변경했습니다.
private void waitForHealthy(Session session, String containerName) throws Exception {
int maxWaitSeconds = 300; // 최대 5분
int intervalSeconds = 5; // 5초마다 체크
int waited = 0;
while (waited < maxWaitSeconds) {
String command = "docker inspect -f '{{.State.Health.Status}}' " + containerName;
String status = executeAndReturnOutput(session, command).trim();
log.info("Health status: " + status);
if ("healthy".equals(status)) {
log.info("Container is healthy.");
return;
}
Thread.sleep(intervalSeconds * 1000);
waited += intervalSeconds;
}
throw new RuntimeException("Container did not become healthy within 5 minutes.");
}
핵심은:
- 5초 간격으로 상태 확인
- healthy가 되면 즉시 다음 단계 진행
- 5분 초과 시 예외 발생
4. 원격 명령 결과를 문자열로 받는 메서드
위 코드에서 사용한 executeAndReturnOutput()은
기존 remoteCommand() 구조를 약간 변형한 것입니다.
private String executeAndReturnOutput(Session session, String command) throws Exception {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
channel.setOutputStream(outputStream);
channel.connect();
while (!channel.isClosed()) {
Thread.sleep(1000);
}
channel.disconnect();
return outputStream.toString();
}
이렇게 하면 단순 로그 출력이 아니라
실제 결과 문자열을 받아서 조건 판단에 사용할 수 있습니다.
5. startRemoteContainer와 연결하기
기존 코드에서는:
Thread.sleep(300000);
이 부분을 완전히 제거하고 다음처럼 변경했습니다.
startRemoteContainer(session, "docker start my_container");
waitForHealthy(session, "my_container");
이제는:
- 컨테이너 시작
- Health 상태가 healthy 될 때까지 대기
- 준비되면 다음 단계 진행
이 흐름이 됩니다.
6. 실제 적용 후 체감 변화
가장 크게 느낀 점은 두 가지였습니다.
① 불필요한 대기 시간 감소
어떤 날은 40초 만에 healthy가 됩니다.
예전 방식이면 무조건 5분을 기다렸을 겁니다.
지금은 준비되면 바로 다음 단계로 넘어갑니다.
② 장애 파악이 쉬워짐
만약 5분 안에 healthy가 되지 않으면
명확하게 예외가 발생합니다.
이전에는 그냥 “5분 기다림 → 다음 단계 실패”였지만
지금은 원인을 정확히 알 수 있습니다.
7. Thread.sleep은 왜 점점 사라지는가
이번 개선을 하면서 느낀 점은 이겁니다.
무조건 대기하는 코드는 불안하다.
상태 기반으로 기다리는 코드는 안정적이다.
자동화 시스템에서는
“시간”이 아니라 “상태”를 기준으로 움직여야 합니다.
마무리
처음에는 Thread.sleep(300000)이 가장 빠른 해결책이었습니다.
하지만 Docker Health Check를 도입하면서 구조가 한 단계 더 올라갔습니다.
'IT > java' 카테고리의 다른 글
| Spring Scheduler 실행 밀림 원인과 5가지 체크리스트 (0) | 2026.06.02 |
|---|---|
| Spring Scheduler 중복 실행 해결 가이드 (0) | 2026.05.26 |
| Java로 SSH 접속, Docker 제어, GitHub Actions 트리거 구현기 (0) | 2026.02.26 |
| 원인을 찾지 못한 트랜잭션 에러, HikariCP를 의심하게 되기까지의 기록 (0) | 2026.01.30 |
| Spring에서 스케줄러를 사용하는 이유(@Scheduled 정리) (0) | 2026.01.29 |