简体   繁体   English

从高山图像中捕获 SIGTERM

[英]Catching SIGTERM from alpine image

I was trying to catch SIGTERM signal from a docker instance (basically when docker stop is called) but couldn't find a way since I have different results for each try I performed.我试图从 docker 实例中捕获 SIGTERM 信号(基本上是在调用 docker stop 时)但找不到方法,因为我执行的每次尝试都有不同的结果。

Following is the setup I have以下是我的设置

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

Now I build the docker image现在我构建了 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

Run the docker运行泊坞窗

$ docker run -it dockertrapcatch

Now when I run docker stop <<container_id_here>> or docker kill --signal=SIGTERM <<container_id_here>> , my deregister_runner function is not called.现在,当我运行docker kill --signal=SIGTERM <<container_id_here>> docker stop <<container_id_here>>docker kill --signal=SIGTERM <<container_id_here>> ,不会调用我的deregister_runner函数。

After that I changed the start.sh script as following (SIGKILL ==> EXIT)之后,我将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

After this change and creating the docker image and running it docker stop <<container_id_here>> still does not work but docker kill --signal=SIGTERM <<container_id_here>> works!在此更改并创建 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

I read that actually docker stop sends a SIGTERM but I think this time it is not working?我读到实际上docker stop发送了一个SIGTERM但我认为这次它不起作用? Any idea?任何的想法?

I can reproduce the issue you raise, while it does not show up when I replace the base image with debian:10 , for example.我可以重现您提出的问题,例如,当我用debian:10替换基本映像时它不会出现。

It happens the issue is not due to alpine but to the gitlab/gitlab-runner:alpine image itself, namely this Dockerfile contains the following line:碰巧这个问题不是由alpine引起的,而是由gitlab/gitlab-runner:alpine图像本身引起的,即这个Dockerfile包含以下行:

STOPSIGNAL SIGQUIT

To be more precise, the line above means docker stop will send a SIGQUIT signal to the running containers (and wait for a "graceful termination time" before killing the containers, as if a docker kill were issued in the end).更准确地说,上面的行意味着docker stop将向正在运行的容器发送一个SIGQUIT信号(并在杀死容器之前等待“正常终止时间”,就好像最后发出了docker kill一样)。

If this Dockerfile directive is not used, the default signal sent by docker stop is SIGTERM .如果未使用此 Dockerfile 指令,则 docker docker stop发送的默认信号为 SIGTERM

Beware that SIGKILL would be a very poor choice for STOPSIGNAL , given that the KILL signal cannot be trapped.请注意, SIGKILL将是STOPSIGNAL一个非常糟糕的选择,因为无法捕获 KILL 信号。

So, your first example should work if you use the following line:因此,如果您使用以下行,您的第一个示例应该可以工作:

trap deregister_runner SIGINT SIGQUIT SIGTERM

This way, your cleanup function deregister_runner will be triggered anytime you issue a docker stop , or use the Ctrl-C keybinding (thanks to SIGINT ).这样,您的清理函数deregister_runner将在您发出docker stop或使用Ctrl-C键绑定(感谢SIGINT )时触发。

Finally, two additional notes related to this question of Docker , bash and signals:最后,关于Dockerbash和信号的这个问题的两个附加说明:

  • The "graceful termination time" (between stop and kill) can be customized, and there are some pitfalls when using a Bash entrypoint (regarding the "signal propagation"). “正常终止时间”(停止和终止之间)可以自定义,并且在使用 Bash 入口点(关于“信号传播”)时存在一些陷阱。 I explained both issues in more detail in this SO answer: Speed up docker-compose shutdown .我在这个 SO 答案中更详细地解释了这两个问题:加速 docker-compose shutdown

  • Beware that in many alpine images, bash is not pre-installed, eg:请注意,在许多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.

    (fortunately, this was not the case of gitlab/gitlab-runner:alpine , which indeed contains the bash package :) (幸运的是,这不是gitlab/gitlab-runner:alpine ,它确实包含bash包:)

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

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