从高山图像中捕捉信号

时间:2019-12-29 17:30:55

标签: docker dockerfile gitlab-ci-runner alpine sigkill

我试图从Docker实例捕获SIGTERM信号(基本上是在调用docker stop时),但找不到方法,因为每次执行的尝试都会产生不同的结果。

以下是我的设置

Dockerfile

FROM gitlab/gitlab-runner:alpine

COPY ./start.sh /start.sh

ENTRYPOINT ["/start.sh"]

start.sh

#!/bin/bash

deregister_runner() {
    echo "even if nothing happened, something happened"
    exit
}
trap deregister_runner SIGTERM

while true; do
    sleep 10
done

现在我构建docker映像

$ docker build -t dockertrapcatch .
Sending build context to Docker daemon  51.71kB
Step 1/3 : FROM gitlab/gitlab-runner:alpine
 ---> 9f8c39873bee
Step 2/3 : COPY ./start.sh /start.sh
 ---> Using cache
 ---> ebb3cac0c509
Step 3/3 : ENTRYPOINT ["/start.sh"]
 ---> Using cache
 ---> 7ab67fe5a714
Successfully built 7ab67fe5a714
Successfully tagged dockertrapcatch:latest

运行docker

$ docker run -it dockertrapcatch

现在,当我运行docker stop <<container_id_here>>docker kill --signal=SIGTERM <<container_id_here>>时,不会调用我的 deregister_runner 函数。

此后,我如下更改了 start.sh 脚本(SIGKILL ==> EXIT)

#!/bin/bash

deregister_runner() {
    echo "even if nothing happened, something happened"
    exit
}
trap deregister_runner EXIT

while true; do
    sleep 10
done

进行此更改并创建docker映像并运行它docker stop <<container_id_here>>仍然不起作用,但是docker kill --signal=SIGTERM <<container_id_here>>起作用!

$ docker run -it dockertrapcatch
even if nothing happened, something happened
$ docker kill --signal=SIGTERM 6b667af4ac6c
6b667af4ac6c

我了解到实际上docker stop发送了 SIGTERM ,但是我认为这一次不起作用?有想法吗?

1 个答案:

答案 0 :(得分:1)

例如,当我用debian:10替换基本图像时,我不会重现您提出的问题。

发生问题的原因不是alpine而是gitlab/gitlab-runner:alpine图片本身,即this Dockerfile包含以下行:

  

STOPSIGNAL SIGQUIT

更确切地说,上面的行表示docker stop将向运行中的容器发送SIGQUIT信号(并在杀死容器之前等待“优美的终止时间”,就像{{ 1}}最终发布了。

如果未使用此Dockerfile指令,则the default signal sent by docker stop is SIGTERM

请注意,由于无法捕获KILL信号,docker kill对于SIGKILL来说是一个非常糟糕的选择。

因此,如果使用以下行,则第一个示例应该可以工作:

STOPSIGNAL

这样,您每次发出trap deregister_runner SIGINT SIGQUIT SIGTERM 或使用deregister_runner键盘绑定(多亏docker stop)时,都会触发清理功能Ctrl-C

最后,还有两个有关此SIGINTDocker问题和信号的注释:

  • 可以自定义“优美的终止时间”(在停止和终止之间),使用Bash入口点时(关于“信号传播”)会有一些陷阱。我在这个SO解答中更详细地解释了这两个问题:Speed up docker-compose shutdown

  • 请注意,在许多bash映像中,alpine尚未预安装,例如:

    bash

    (幸运的是,$ sudo docker run --rm -it alpine /bin/bash /usr/bin/docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"/bin/bash\": stat /bin/bash: no such file or directory": unknown. 并非如此,它确实包含gitlab/gitlab-runner:alpine包:)