저는 tini
컨테이너의 셸 스크립트를 통해 Java 애플리케이션을 시작하고 컨테이너가 중지될 때 내 애플리케이션이 Docker로부터 신호를 받도록 하기 위해 init 프로세스로 사용합니다. 문제는 컨테이너 내부의 프로세스 목록에 있는 내용을 표시하는 것만으로도 가장 잘 설명되므로 설정에 대해 간략하게 설명하겠습니다.
startup.sh
Java 애플리케이션을 설정하기 위해 실행해야 하는 쉘 스크립트가 있습니다 . 그러면 애플리케이션이 설정되고 실행됩니다. 일반적으로 이 스크립트는 포그라운드에서 Java를 시작합니다. 디버깅을 위해 스크립트가 백그라운드에서 Java 애플리케이션을 시작한 다음 bash 셸을 시작하도록 했습니다. 어느 쪽이든 동일한 문제가 있는 동작을 봅니다.
내 Dockerfile에는 다음 두 줄이 있습니다.
ENTRYPOINT ["/tini", "-g", "--"]
CMD ["./bin/startup.sh"]
Startup.sh 스크립트 맨 아래에서 내 Java 애플리케이션은 다음과 같이 시작됩니다.
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 -Dfilethis.root.dir=/home/fetch/fetchbase -jar bin/fetch.jar
나는 bash가 신호를 투명하게 전달하지 않는다는 것을 항상 알고 있었습니다. 구글링해서 해결책을 찾았습니다 tini
. 내가 읽은 바에 따르면 -g
to 옵션을 사용하면 tini
직계 자식 프로세스뿐만 아니라 해당 자식 프로세스에 의해 시작된 프로세스에도 신호를 전달해야 합니다. 왜냐하면 모두 동일한 프로세스 그룹에 있기 때문입니다.
디버그 모드를 사용하여 컨테이너 내부에 셸을 가져오면 프로세스 목록에 다음이 표시됩니다.
sh-4.2$ ps -ae -o pid,ppid,gid,cmd
PID PPID GID CMD
1 0 1000 /tini -g -- ./bin/startup.sh
8 1 1000 /bin/sh ./bin/startup.sh
16 8 1000 /usr/bin/Xvfb :15 -screen 0 1280x1024x24
42 1 0 /usr/sbin/sshd
44 8 1000 java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005 -Dfilethis.root.dir=/home/fetch/fetchbase -jar bin/fetch.jar
45 8 1000 /bin/sh
63 45 1000 ps -ae -o pid,ppid,gid,cmd
이 정도가 맞는 것 같습니다. p#1은 tini
Java 애플리케이션인 p#44를 시작하는 쉘 스크립트인 p#8을 시작합니다. 세 프로세스 모두 ID가 1000인 동일한 프로세스 그룹에 있습니다.
Java 프로세스에 디버거를 배치하고 분해 코드(애플리케이션이 TERM 신호를 수신할 때 실행되는 코드)의 여러 위치에 중단점을 설정했습니다. 그런 다음 다음 두 명령 중 하나를 실행합니다.
1) kill -TERM 1
2) kill -TERM 44
첫 번째 경우 Docker가 컨테이너를 닫으면(맞죠?) 애플리케이션에서 중단점이 적중되지 않고 컨테이너가 즉시 종료됩니다. 애플리케이션에 넣은 로깅을 통해 분해 코드가 실행되지 않았음을 확인했습니다. 이 경우 tini
TERM 신호를 Java 애플리케이션에 전달하면 안 되나요?
두 번째 경우에는 디버거에서 중단점에 도달하고 로그에 해체 코드가 실행되었음을 표시합니다.
컨테이너가 시작될 때 Java 애플리케이션이 셸 스크립트를 통해 포그라운드에서 실행된 다음 docker stop
컨테이너에서 실행될 때 동일한 동작이 발생합니다. 중단점과 해제 코드가 적중되지 않습니다.
내가 무엇을 놓치고 있나요? tini
신호 전파의 의미를 오해한 걸까요 ? 티아!