在 Docker 容器内,“tini”应该将信号代理到我的 Java 应用程序,但它似乎没有这样做

在 Docker 容器内,“tini”应该将信号代理到我的 Java 应用程序,但它似乎没有这样做

我使用tini作为我的 init 进程来允许我通过容器中的 shell 脚本启动 Java 应用程序,并让我的应用程序在容器停止时从 Docker 获取信号。鉴于仅通过显示容器内的进程列表中的内容即可很好地展示问题,因此我将简要介绍我的设置。

我有一个 shell 脚本startup.sh,需要运行它来为我的 Java 应用程序进行设置。它会进行设置,然后运行应用程序。通常,该脚本在前台启动 Java。为了进行调试,我让脚本在后台启动我的 Java 应用程序,然后启动 bash shell。无论哪种方式,我都看到同样有问题的行为。

我的 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。根据我的阅读,如果我使用选项-gto tini,那么它不仅应该将信号转发到其直接子进程,还应该转发到该子进程启动的进程,因为它们都位于同一进程组中。

当我使用调试模式在容器内获取 shell 时,我在进程列表中看到以下内容:

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#1tini启动了 p#8,我的 shell 脚本,它启动了 p#44,我的 Java 应用程序。所有三个进程都位于 id 1000 的同一进程组中。

我将调试器放在 Java 进程上,并在拆卸代码中的几个位置设置断点...当应用程序收到 TERM 信号时将运行的代码。然后我运行两个命令之一:

1) kill -TERM 1

2) kill -TERM 44

在第一种情况下,如果 Docker 关闭容器(对吗?),我的应用程序中不会命中断点,容器会立即终止。我在应用程序中放入的日志记录确认我的拆卸代码从未运行。在这种情况下,不应该tini将 TERM 信号传递给我的 Java 应用程序吗?

在第二种情况下,我的断点在调试器中被命中,日志显示我的拆卸代码已运行。

当我的 Java 应用程序在容器启动时通过 shell 脚本在前台运行时,我会得到相同的行为,然后我docker stop在容器上执行...我的断点和拆卸代码不会被命中。

我缺少什么?我是否误解了tini传播信号的含义?蒂亚!

相关内容