docker stop对节点进程不起作用

时间:2021-05-29 21:14:22

I want to be able to run node inside a docker container, and then be able to run docker stop <container>. This should stop the container on SIGTERM rather than timing out and doing a SIGKILL. Unfortunately, I seem to be missing something, and the information I have found seems to contradict other bits.

我希望能够在docker容器中运行node,然后能够运行docker stop 。这应该在SIGTERM上停止容器,而不是超时并执行SIGKILL。不幸的是,我似乎遗漏了一些东西,我发现的信息似乎与其他部分相矛盾。

Here is a test Dockerfile:

这是一个测试Dockerfile:

FROM ubuntu:14.04
RUN apt-get update && apt-get install -y curl
RUN curl -sSL http://nodejs.org/dist/v0.11.14/node-v0.11.14-linux-x64.tar.gz | tar -xzf -
ADD test.js /
ENTRYPOINT ["/node-v0.11.14-linux-x64/bin/node", "/test.js"]

Here is the test.js referred to in the Dockerfile:

这是Dockerfile中引用的test.js:

var http = require('http');

var server = http.createServer(function (req, res) {
  console.log('exiting');
  process.exit(0);
}).listen(3333, function (err) {
  console.log('pid is ' + process.pid)
});

I build it like so:

我像这样构建它:

$ docker build -t test .

I run it like so:

我像这样运行它:

$ docker run --name test -p 3333:3333 -d test

Then I run:

然后我跑:

$ docker stop test

Whereupon the SIGTERM apparently doesn't work, causing it to timeout 10 seconds later and then die.

因此,SIGTERM显然不起作用,导致它在10秒后超时,然后死亡。

I've found that if I start the node task through sh -c then I can kill it with ^C from an interactive (-it) container, but I still can't get docker stop to work. This is contradictory to comments I've read saying sh doesn't pass on the signal, but might agree with other comments I've read saying that PID 1 doesn't get SIGTERM (since it's started via sh, it'll be PID 2).

我发现如果我通过sh -c启动节点任务,那么我可以用交互式(-it)容器中的^ C来杀死它,但我仍然无法让docker停止工作。这与我读过的评论相矛盾,说sh不传递信号,但可能同意我读过的其他评论说PID 1没有得到SIGTERM(因为它是通过sh启动的,它将是PID 2)。

The end goal is to be able to run docker start -a ... in an upstart job and be able to stop the service and it actually exits the container.

最终目标是能够在upstart作业中运行docker start -a ...并能够停止服务并实际退出容器。

1 个解决方案

#1


1  

Ok, I figured out a workaround myself, which I'll venture as an answer in the hope it helps others. It doesn't completely answer why the signals weren't working before, but it does give me the behaviour I want.

好吧,我想出了一个自己的解决方法,我会冒昧地回答,希望能帮助别人。它并没有完全回答为什么信号之前没有工作,但它确实给了我想要的行为。

Using baseimage-docker seems to solve the issue. Here's what I did to get this working with the minimal test example above:

使用baseimage-docker似乎解决了这个问题。以下是我使用上面的最小测试示例进行的操作:

Keep test.js as is.

保持test.js不变。

Modify Dockerfile to look like the following:

将Dockerfile修改为如下所示:

FROM phusion/baseimage:0.9.15

# disable SSH
RUN rm -rf /etc/service/sshd /etc/my_init.d/00_regen_ssh_host_keys.sh

# install curl and node as before
RUN apt-get update && apt-get install -y curl
RUN curl -sSL http://nodejs.org/dist/v0.11.14/node-v0.11.14-linux-x64.tar.gz | tar -xzf -

# the baseimage init process
CMD ["/sbin/my_init"]

# create a directory for the runit script and add it
RUN mkdir /etc/service/app
ADD run.sh /etc/service/app/run

# install the application
ADD test.js /

baseimage-docker includes an init process (/sbin/my_init) which handles starting other processes and dealing with zombie processes. It uses runit for service supervision. The Dockerfile therefore sets the my_init process as the command to run on boot, and adds a script /etc/service for runit to pick it up.

baseimage-docker包含一个init进程(/ sbin / my_init),用于处理启动其他进程和处理僵尸进程。它使用runit进行服务监督。因此,Dockerfile将my_init进程设置为在引导时运行的命令,并为runit添加脚本/ etc / service以获取它。

The run.sh script is simple:

run.sh脚本很简单:

#!/bin/sh
exec /node-v0.11.14-linux-x64/bin/node /test.js

Don't forget to chmod +x run.sh!

别忘了chmod + x run.sh!

By default, runit will automatically restart the service if it goes down.

默认情况下,如果服务出现故障,runit将自动重启服务。

Following these steps (and build, run, and stop as before), the container properly responds to requests for it to shutdown, in a timely fashion.

按照这些步骤(以及之前的构建,运行和停止),容器会及时正确地响应其关闭请求。

#1


1  

Ok, I figured out a workaround myself, which I'll venture as an answer in the hope it helps others. It doesn't completely answer why the signals weren't working before, but it does give me the behaviour I want.

好吧,我想出了一个自己的解决方法,我会冒昧地回答,希望能帮助别人。它并没有完全回答为什么信号之前没有工作,但它确实给了我想要的行为。

Using baseimage-docker seems to solve the issue. Here's what I did to get this working with the minimal test example above:

使用baseimage-docker似乎解决了这个问题。以下是我使用上面的最小测试示例进行的操作:

Keep test.js as is.

保持test.js不变。

Modify Dockerfile to look like the following:

将Dockerfile修改为如下所示:

FROM phusion/baseimage:0.9.15

# disable SSH
RUN rm -rf /etc/service/sshd /etc/my_init.d/00_regen_ssh_host_keys.sh

# install curl and node as before
RUN apt-get update && apt-get install -y curl
RUN curl -sSL http://nodejs.org/dist/v0.11.14/node-v0.11.14-linux-x64.tar.gz | tar -xzf -

# the baseimage init process
CMD ["/sbin/my_init"]

# create a directory for the runit script and add it
RUN mkdir /etc/service/app
ADD run.sh /etc/service/app/run

# install the application
ADD test.js /

baseimage-docker includes an init process (/sbin/my_init) which handles starting other processes and dealing with zombie processes. It uses runit for service supervision. The Dockerfile therefore sets the my_init process as the command to run on boot, and adds a script /etc/service for runit to pick it up.

baseimage-docker包含一个init进程(/ sbin / my_init),用于处理启动其他进程和处理僵尸进程。它使用runit进行服务监督。因此,Dockerfile将my_init进程设置为在引导时运行的命令,并为runit添加脚本/ etc / service以获取它。

The run.sh script is simple:

run.sh脚本很简单:

#!/bin/sh
exec /node-v0.11.14-linux-x64/bin/node /test.js

Don't forget to chmod +x run.sh!

别忘了chmod + x run.sh!

By default, runit will automatically restart the service if it goes down.

默认情况下,如果服务出现故障,runit将自动重启服务。

Following these steps (and build, run, and stop as before), the container properly responds to requests for it to shutdown, in a timely fashion.

按照这些步骤(以及之前的构建,运行和停止),容器会及时正确地响应其关闭请求。