SIGTERM not received by java process using 'docker stop' and the official java image

此生再无相见时 提交于 2019-12-02 18:07:15

Assuming you launch a Java service by defining the following in your Dockerfile:

CMD java -jar ...

When you now enter the container and list the processes e.g. by docker exec -it <containerName> ps AHf (I did not try that with the java but with the ubuntu image) you see that your Java process is not the root process (not the process with PID 1) but a child process of a /bin/sh process:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 18:27 ?        00:00:00 /bin/sh -c java -jar ...
root         8     1  0 18:27 ?        00:00:00   java -jar ...

So basically you have a Linux shell that is the main process with PID 1 which has a child process (Java) with PID 8.

To get signal handling working properly you should avoid those shell parent process. That can be done by using the builtin shell command exec. That will make the child process taking over the parent process. So at the end the former parent process does not exist any more. And the child process becomes the process with the PID 1. Try the following in your Dockerfile:

CMD exec java -jar ...

The process listing then should show something like:

UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 18:30 ?        00:00:00 java -jar ...

Now you only have that one process with PID 1. Generally a good practice is to have docker containers only contain one process - the one with PID 1 (or if you really need more processes then you should use e.g. supervisord as PID 1 which itself takes care of signal handling for its child processes).

With that setup the SIGTERM will be treated directly by the Java process. There is no shell process any more in between which could break signal handling.

EDIT:

The same exec effect could be achieved by using a different CMD syntax that does it implicitly (thanks to Andy for his comment):

CMD ["java", "-jar", "..."]

@h3nrik answer is right but sometimes you really need to use a script for setup the launch. Just use the exec command to do the trick in most of the cases:

#!/bin/sh

#--- Preparations

exec java -jar ...

See this wonderful blog post

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!