[FEAT] 비동기 작업 유실 완화를 위한 Graceful Shutdown 적용#98
Conversation
WalkthroughGraceful shutdown을 구현하기 위해 Docker 컨테이너, Spring Boot 애플리케이션 설정, 그리고 생명주기 모니터링을 함께 개선했어요. 프로세스 교체, 종료 대기 시간 설정, health probe 활성화, 그리고 종료 이벤트 로깅이 추가되었습니다. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20분 설정과 코드 변경이 섞여 있고 여러 파일에 걸쳐 있지만, 각 변경의 의도가 명확하고 graceful shutdown의 전체적인 맥락을 이해하면 검토할 수 있어요. Docker, Spring Boot 설정, 그리고 자바 코드의 조화를 함께 살펴봐야 한다는 점이 검토 복잡도를 약간 높이고 있습니다. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Dockerfile (1)
12-20: 🧹 Nitpick | 🔵 Trivial런타임 이미지를 non-root 사용자로 실행해 주세요.
현재 최종 stage에
USER지시어가 없어 애플리케이션이 root로 실행되고 있어요. graceful shutdown 목적의exec java변경은 좋지만, 운영 이미지에서는 전용 사용자를 만들고USER를 지정하는 편이 보안 관점에서 더 안전합니다.docker-compose.yml에서 마운트하는firebase-service-account.json은 선택한 UID/GID로 읽을 수 있도록 소유권을 설정해야 합니다.🔐 권장 변경 예시
FROM eclipse-temurin:17-jre-alpine WORKDIR /app +RUN addgroup -S app && adduser -S app -G app COPY --from=builder /app/build/libs/*.jar app.jar +RUN chown app:app /app/app.jar EXPOSE 8080 +USER app ENTRYPOINT ["sh", "-c", "exec java ${JAVA_OPTS} -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod} -jar /app/app.jar"]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Dockerfile` around lines 12 - 20, The final image currently runs as root; add a non-root runtime user and switch to it by creating a dedicated user (e.g., app user) and adding a USER directive in the final stage so ENTRYPOINT ["sh", "-c", "exec java ... -jar /app/app.jar"] runs unprivileged; ensure files under WORKDIR (the copied app.jar) are owned by that user (adjust COPY/ownership in the final stage or use chown during image build) and document that the docker-compose mount for firebase-service-account.json must set the same UID/GID (or change ownership in the container at startup) so the non-root user can read it.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@Dockerfile`:
- Around line 12-20: The final image currently runs as root; add a non-root
runtime user and switch to it by creating a dedicated user (e.g., app user) and
adding a USER directive in the final stage so ENTRYPOINT ["sh", "-c", "exec java
... -jar /app/app.jar"] runs unprivileged; ensure files under WORKDIR (the
copied app.jar) are owned by that user (adjust COPY/ownership in the final stage
or use chown during image build) and document that the docker-compose mount for
firebase-service-account.json must set the same UID/GID (or change ownership in
the container at startup) so the non-root user can read it.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: ASSERTIVE
Plan: Pro
Run ID: a4dc560a-62d5-454b-af76-2aaa3045758c
📒 Files selected for processing (4)
Dockerfiledocker-compose.ymlsrc/main/java/com/project/dorumdorum/global/alert/ApplicationLifecycleAlertListener.javasrc/main/resources/application-prod.yml
📌 제목
📢 요약
🔗 연관 이슈: Resolves #89
🚀 PR 유형
✅ PR 체크리스트
📜 기타
application-prod.yml에server.shutdown=graceful,spring.lifecycle.timeout-per-shutdown-phase=30s를 적용했습니다.application-prod.yml에 readiness/liveness probe를 활성화해/actuator/health/readiness,/actuator/health/liveness를 운영 헬스체크 경로로 사용할 수 있게 했습니다.Dockerfile은exec java ...형태로 수정해SIGTERM이 JVM에 직접 전달되도록 변경했습니다.docker-compose.yml의backend서비스에stop_grace_period: 45s를 추가해 앱의 30초 종료 대기 시간을 컨테이너 레벨에서 보장하도록 했습니다.prod프로필 기동으로 수행했습니다.SIGTERM전송 시 readiness가REFUSING_TRAFFIC으로 전환되고, 진행 중이던 15초 요청이200 OK로 완료된 뒤 프로세스가 종료되는 것을 확인했습니다./actuator/health/readiness를 기준으로 트래픽 드레이닝을 수행해야 합니다.Summary by CodeRabbit
개선 사항