繁体   English   中英

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

[英]SIGTERM does not reach node script when docker runs it with `/bin/sh -c`

当我的Dockerfile结束时

CMD node .

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

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

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

问题是,当我将SIGTERM发送到容器(以/bin/sh -c "node ."开头)时,通过docker-composer stopdocker-composer kill -s SIGTERM ,信号不会到达我的node进程,因此在10秒宽限期后,每次使用SIGKILL强行杀死它。 不是很好。

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

我认为你必须了解的角色ENTRYPOINTCMD ,并使用ENTRYPOINT在(EXEC形式)的方式Dockerfile

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

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

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

  • exec形式:ENTRYPOINT [“executable”,“param1”,“param2”]
  • shell form:命令param1 param2

正如Docker引用所指出的那样:建议使用exec表单,而shell表单的缺点是命令/bin/bash -c ,这可能不适用于信号:

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

有一些工具旨在解决这个问题:

我想如果你只有一个进程,你需要做的只是使用信号处理程序显式处理信号,bash不适合你。

使用["node", "."]语法,您可以使用https://nodejs.org/api/process.html#process_signal_events并让它退出SIGTERM。 我相信这就足够了。

或者使用bash脚本,您可以使用trap "exit 0" TERM

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

我对PID1问题的解决方案:

Dockerfile以:

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

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

比我运行这个shell脚本,它的文件名是node并且有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 $@"

诀窍是"echo pid1 > /dev/null && node $@"这是命令。 $@是一个shell脚本,用于接受来自命令行的用户输入。

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

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

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

是我的Dockerised Node.js开发环境。

编辑:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM