当前位置: 首页 > 面试题库 >

使用'docker stop'和官方Java映像的Java进程未收到SIGTERM

岑熙云
2023-03-14
问题内容

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

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

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

我的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?还有其他方法可以解决这个问题吗?


问题答案:

假设通过在您的中定义以下内容来启动Java服务Dockerfile

CMD java -jar ...

现在,当您进入容器并列出进程时,例如,通过docker exec -it <containerName> ps AHf(我没有尝试使用,java而是使用ubuntu图像),您会看到Java进程不是根进程(不是PID为1的进程),而是a的子进程。/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外壳程序,它是PID 1的主要进程,而Linux外壳程序具有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 ...

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

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

编辑

exec通过使用不同的CMD隐式语法可以达到相同的效果

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


 类似资料:
  • 问题内容: 我正在使用这个官方的php Docker映像:[https]( https://github.com/docker- library/php/blob/76a1c5ca161f1ed6aafb2c2d26f83ec17360bc68/7.1/alpine/Dockerfile) //github.com/docker- library/php/blob/76a1c5ca161f1ed6

  • 问题内容: 我通过运行此命令为Tomcat提取了官方Docker镜像。 通过使用它作为基本映像,我需要构建新映像,该映像在 文件夹中包含我的war文件。我这样创建了Dockerfile。 当我通过构建映像运行此Dockerfile时,无法看到Tomcat主页。 谁能告诉我如何将我的warfile添加到官方Tomcat图像webapp文件夹中。 问题答案: 从仓库的文档中读取内容,您会做类似的事情

  • 主要内容:初始程序,执行步骤前面我们已经看到了如何获得进程及其父进程的基本信息,现在来查看进程/程序信息的细节。 进程映像究竟是什么? 进程映像是执行程序时所需的可执行文件。 该图片通常包含以下部分 - 代码段或文本段 数据段 堆栈段 堆段 以下是进程映像的图形表示。参考下图 - 代码段是由可执行指令组成的目标文件或程序虚拟地址空间的一部分。 这通常是只读数据段,具有固定的大小。 数据段有两种类型。分别如下所示 - 初始化

  • 我正在尝试运行Jersey的HelloWorld示例,但失败了。这就是我尝试过的。 我已经设置我的这样 我已经设置了我的像这样, 我的服务设置是这样的, 我正在使用这些libs 这是这个问题的视频http://screencast.com/t/oIYKMQw1x 知道我做错了什么吗? 谢谢 堆栈跟踪 Apr 23,2012 12:19:27 AMcom.sun.jersey.server.impl

  • 问题内容: 假设我有一个void方法,该方法只对对象进行转换而没有返回任何值,并且我想在流map()函数的上下文中使用它,如下所示: 该示例是为了简单起见而构成的-实际方法除了在处理对象的UUID之外,还在做其他事情。 无论如何,在上述情况下如何使用void方法?当然,我可以使该方法返回转换后的对象,但这不重要,并且违反了设计(该方法应为空)。 问题答案: 似乎是强制使用Java 8流的情况。相反

  • 假设我有一个对对象进行转换而不返回任何值的空方法,我想在stream map()函数的上下文中使用它,如下所示: 这个例子是为了简单起见——实际的方法不仅仅是搞乱对象的UUID。 不管怎样,在上面这样的场景中如何使用空方法?当然,我可以让该方法返回转换后的对象,但这不是重点,并且违反了设计(该方法应该是空的)。