使用'docker stop'和官方Java映像的Java进程未收到SIGTERM [英] SIGTERM not received by java process using 'docker stop' and the official java image

查看:151
本文介绍了使用'docker stop'和官方Java映像的Java进程未收到SIGTERM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用基于 debian / jessie java:7u79 在Docker容器中运行dropwizard Java应用程序>。

I am running a dropwizard Java application in a Docker container using the image java:7u79 based on debian/jessie.

我的Java应用程序处理 SIGTERM 信号以正常关闭。当我在没有Docker的情况下运行应用程序时, SIGTERM 的处理效果非常好。

My Java application handles the SIGTERM signal to shutdown gracefully. The SIGTERM handling works perfect when I run the application without Docker.

在Docker容器中运行该应用程序时,当我发出 docker stop 命令时, SIGTERM 无法到达Java应用程序。它会在10秒后突然终止该进程。

When I run it in a Docker container the SIGTERM does not reach the Java application when I issue a docker stop command. It kills the process abruptly after 10 seconds.

我的 Dockerfile

FROM java:7u79

COPY dropwizard-example-1.0.0.jar /opt/dropwizard/
COPY example.keystore /opt/dropwizard/
COPY example.yml /opt/dropwizard/

WORKDIR /opt/dropwizard

RUN java -jar dropwizard-example-1.0.0.jar db migrate /opt/dropwizard/example.yml

CMD java -jar dropwizard-example-1.0.0.jar server /opt/dropwizard/example.yml

EXPOSE 8080 8081

Dockerfile有什么问题 ?还有其他方法可以解决此问题吗?

What is wrong with this Dockerfile? Is there any other way to tackle this problem?

推荐答案

假设您通过在<$ c中定义以下内容来启动Java服务$ c> Dockerfile :

CMD java -jar ...

当您现在进入容器并列出过程时,例如通过 docker exec -it< containerName> ps AHf (我没有尝试使用 java 而是使用 ubuntu 图片)您会看到Java进程不是根进程(不是PID为1的进程),而是 / bin / sh 进程的子进程:

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 ...

所以基本上您拥有一个Linux shell PID 1的主进程具有一个PID 8的子进程(Java)。

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

要使信号处理正常工作,您应该避免使用这些shell父进程。这可以通过使用内置的shell命令 exec 来完成。这将使子进程接管父进程。因此最后,以前的父进程不再存在。然后子进程将成为具有PID的进程。在 Dockerfile 中尝试以下操作:

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 ...

现在您只有一个使用PID 1的进程通常,一个好的做法是让docker容器仅包含一个进程-一个具有PID 1的进程(或者,如果您确实需要更多进程,则应使用例如 supervisord 作为PID 1,它本身负责其子进程的信号处理。)

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).

使用该设置, SIGTERM 将直接由Java进程处理。在它们之间不再有任何shell过程可以破坏信号处理。

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

通过使用不同的 CMD 隐式执行语法,可以实现相同的 exec 效果(感谢安迪(他的评论):

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", "..."]

这篇关于使用'docker stop'和官方Java映像的Java进程未收到SIGTERM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆