当前位置: 首页 > 知识库问答 >
问题:

当docker使用'/bin/sh-c'运行SIGTERM时,SIGTERM不会到达节点脚本

傅嘉悦
2023-03-14

当我的Dockerfile以

CMD node .

Docker使用命令/bin/sh-c"节点."来运行该容器。而不是简单的节点。(我知道,我可以用CMD["节点", "."] )。

我认为这种行为实际上很好,因为它意味着容器中的PID1/bin/sh,而不是我简单的节点脚本。

如果我正确理解PID1负责收获孤儿僵尸进程,我真的不想对此负责...所以如果/bin/sh可以做到这一点,那就太好了。(我实际上认为这是docker重写我的CMD的原因)。

问题是,当我发送一个SIGTERM到容器(以/bin/sh-c"节点"开始。),通过docker-作曲家停止docker-作曲家杀死-s SIGTERM,信号没有到达我的节点进程,因此在10秒的宽限期后,它每次都被强制杀死。不漂亮。

有没有办法让某人管理我的僵尸,让我的节点实例接收docker发送的信号?


共有3个答案

孔和畅
2023-03-14

我的PID1问题解决方案:

Dockerfile以以下内容结束:

ENTRYPOINT ["/bin/bash", "-c"]

或者将ENTRYPOINT完全从Dockerfile中删除。默认值为/bin/sh-c

比我运行这个外壳脚本,它具有节点的文件名,并且具有chmod x

#!/bin/bash

docker run --rm -it -p 8083:80 -v $HOME/node/work/:/root/node/:rw node_node "echo pid1 > /dev/null && node $@"

诀窍是回声pid1

echo将捕获PID1并将输出发送到/dev/null

例如./node-v将在运行的容器中返回Node.js的版本。

使用/node/root/node/hello world.js命令运行Web服务器时,CTRL C将再次工作。

这是我的DockerizedNode.js开发环境。

编辑:

完全疯狂的想法,但是将这个名为bash脚本的节点添加到$PATH。所以在主机上,您可以键入节点-v而不是./节点-v。你在Docker容器中运行节点,它看起来完全像是安装在主机上的。:)

管杜吟
2023-03-14

有一些工具可以解决这个问题:

  • https://github.com/yelp/dumb-init
  • https://github.com/krallin/tini

我认为如果你只有一个进程,你所需要做的就是用一个信号处理程序显式处理信号,而bash对你没有用。

使用[“node”,“]语法,您可以使用https://nodejs.org/api/process.html#process_signal_events 让它在一个学期内退出。我相信这就足够了。

或者使用bash脚本,您可以使用陷阱"退出0"TERM

您也可以使用像http://skarnet.org/software/s6/这样的流程主管

郭云
2023-03-14

我认为您必须了解ENTRYPOINTCMD的角色,并在Dockerfile中使用ENTRYPOINT(exec表单)方式。

ENTRYPOINT,指定容器的起始可执行文件,是Docker容器的核心部分。每个容器都必须有一个入口点来决定从何处开始。默认情况下,该值为/bin/bash-c。此外,CMD设置的所有内容都将作为参数附加到ENTRYPOINT

因此,如果您未能在Dockerfile中指定ENTRYPOINT,那么实际的入口点将是/bin/bash-c{your_command_in_CMD},不幸的是,它不会传递信号。

ENTRYPOINT有两种形式:exec形式和shell形式

  • exec form: ENTRYPOINT[可执行文件,参数1,参数2]
  • shell形式:命令参数1参数2

正如Docker参考资料所指出的:建议使用exec表单,而shell表单的缺点是命令由/bin/bash-c执行,这可能无法很好地处理信号:

shell表单阻止使用任何CMDrun命令行参数,但有一个缺点,即您的ENTRYPOINT将作为/bin/sh-c的子命令启动传递信号。这意味着可执行文件将不是容器的PID 1-并且不会接收Unix信号-因此您的可执行文件将不会从docker停止接收SIGTERM

 类似资料:
  • 问题内容: 我正在使用以下命令构建新的Docker映像: 但是,它失败并显示以下错误: 这似乎在我的本地计算机(Mac OSX)上运行良好,但是当我尝试在Linux CentOS 7计算机上构建它时,它失败了。 问题答案: 最后,我们升级了项目以使用此Docker Maven插件:https : //github.com/fabric8io/fabric8-maven- plugin 。到目前为止

  • 我正在从Bash脚本启动一个名为 的Java代码。Bash 脚本启动 Java 代码,然后运行 Java 代码。在Java程序结束时,我想发送一个信号回到Bash脚本以终止。请记住,Bash 脚本在 PID = 1 的情况下运行。我必须杀死PID 1过程。 我设置了bash脚本,使其在无限循环中运行,并< code >等待终止信号: 我正在使用Docker实例,信号是< code>sigterm。

  • 我在跟踪stackoverflow的帖子 我应该以什么顺序向正常关闭进程发送信号? 并遇到了以下声明。请帮助我理解我以粗体标记的部分。[在答案中找到3票] 守护进程有时使用SIGHUP重新启动或重新加载配置的原因是守护进程从任何控制终端分离,因此永远不会接收SIGTERM,因此该信号被视为“释放”供一般使用。

  • 这是我的Dockerfile的内容。 当我运行Dockerfile来构建docker映像时,我得到以下错误: /bin/sh:1:sudo:未找到 你能帮我解决上面的错误吗?

  • 按预期更正代码:从多处理导入池导入信号导入时间导入操作系统 ================================================== 我发现了问题,当我使用map函数时,主func被阻塞,只有map函数被funish时才会调用信号处理程序。所以,使用"map_async"函数来解决这个问题要好得多。 以下是我的发现: 纯用C语言实现的长时间运行的计算(例如对大量文本进行

  • 问题内容: 我正在创建节点命令行界面。它是全局安装的,并使用bin文件执行。 我计划在正在处理的文件的根目录下打开一个命令窗口,然后运行命令,但是由于返回节点包的目录,我无法确定当前的工作目录。最初,我假设由于代码是使用批处理文件作为包装器执行的(这就是bin文件可以在开始时没有节点的情况下执行的方式),所以这是不可能的,但是coffee- script可以做到这一点。我看了看咖啡脚本的源代码,但