ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 왜 Dockerfile에서 Java 프로세스를 exec form으로 실행해야 하는가?
    Docker 2025. 5. 21. 00:19
    (-) CMD ["sh", "-c", "java $JVM_OPTS -jar app.jar"]
    (+) CMD ["sh", "-c", "exec", "java $JVM_OPTS -jar app.jar"]
    "자바 어플리케이션이 1번 프로세스가 되어야 합니다."

    멘토님의 Dockerfile에 대한 피드백과 참조해주신 문서에 대해 간단히 정리한 글입니다.

    상황 : Java 애플리케이션을 실행시키기 위한 컨테이너 이미지를 빌드하려는 목적으로 작성한 Dockerfile에, app.jar 명령어를 실행시키는 부분에서 받은 피드백입니다.

     

    java 애플리케이션의 PID 1 프로세스로 배정하라

    프로세스란?

    Linux/Unix 시스템에서 어떤 프로그램을 실행하면, 프로세스에서 실행된다.

    그리고 어떤 프로세스(A)가 다른 프로세스(B)를 실행하면, 그건 자식 프로세스(child process)(B)가 된다.

     

    Docker 명령어 실행과 프로세스 배정 예시

    e.g. shell(A), java(B)

    ENTRYPOINT ["sh", "-c", "java -jar app.jar"]
    
    
    PID 1: sh (A)
    └── PID 2: java (B)

     

    e.g. java(B)

    ENTRYPOINT ["sh", "-c", "exec java -jar app.jar"]
    
    PID 1: java
    

     

    이때 Docker 는 SIGTERM, SIGINT 같은 시그널을 PID 1에게만 직접 보낸다.

    PID 1이 sh일 때, SIGTERM 시그널을 받았다면, 또한 시그널 전달 코드가 작성되어 있지 않다면 PID 2에서 돌아가는 java 는 신호를 받지 못해 좀비 프로세스가 된다.

     

    shell form vs exec from

    즉, shell form은 PID 1에서는 Shell을, PID 8 등의 다른 PID에서는 스크립트를 실행시킨다. 이때, PID 1은 컨테이너의 메인 프로세스이다. 컨테이너를 중지시킬 때, 메인 프로세스에 자식이 딸려있으면 메인 프로세스가 자식 프로세스들의 종료를 처리해야 한다. 하지만 shell form에서는 PID 1인 Shell이 받은 종료 신호를 자식 프로세스(실제 애플리케이션)에게 전달하지 않는 문제가 있다. 따라서 애플리케이션이 직접 종료 신호를 받아 처리할 수 있도록 exec form을 써야한다.

     


    [참고 자료]

    https://brunch.co.kr/@growthminder/142 

    https://engineering.pipefy.com/2021/07/30/1-docker-bits-shell-vs-exec/

     

    'Docker' 카테고리의 다른 글

    docker-compose.yml 의 이용  (0) 2025.04.03
Designed by Tistory.