SIGTERM没有被java进程使用’docker stop’和官方java图像接收

前端之家收集整理的这篇文章主要介绍了SIGTERM没有被java进程使用’docker stop’和官方java图像接收前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用基于debian / jessie的图像 java:7u79在Docker容器中运行dropwizard Java应用程序.

我的Java应用程序处理SIGTERM信号正常关闭.当我运行没有Docker的应用程序时,SIGTERM处理功能非常完美.

当我在Docker容器中运行它时,当我发出docker stop命令时,SIGTERM不会到达Java应用程序. 10秒钟后,它会突然死亡.

我的Docker文件

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

这个Docker文件有什么问题?有什么办法可以解决这个问题吗?

解决方法

假设您通过在Dockerfile中定义以下内容来启动Java服务:
CMD java -jar ...

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

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

要使信号处理正常工作,您应该避免这些shell父进程.这可以通过使用内置shell命令exec来完成.这将使子进程接管父进程.所以最后,前一个父进程不再存在了.并且子进程成为PID 1的过程.请在Dockerfile中尝试以下操作:

CMD exec java -jar ...

过程列表应该显示如下:

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,它本身采取照顾其子进程的信号处理).

使用该设置,SIGTERM将被Java进程直接处理.没有任何shell进程之间可能会中断信号处理.

编辑:

通过使用不同的CMD语法来隐含地实现同样的执行效果(感谢Andy评论):

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

猜你在找的Java相关文章