docker - 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.
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 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.
After that I changed the start.sh script as following (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 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? Any idea?
解决方案
我可以重现您提出的问题,但是当我用 替换基本图像时它不会出现debian:10
,例如。
碰巧问题不是由于图像本身alpine
而是由于gitlab/gitlab-runner:alpine
图像本身,即它Dockerfile
包含以下行:
STOPSIGNAL SIGQUIT
更准确地说,上面的行意味着docker stop
将向正在运行的容器发送SIGQUIT
信号(并在杀死容器之前等待“优雅终止时间”,就好像docker kill
最后发出了 a 一样)。
如果不使用此 Dockerfile 指令,则发送的默认信号docker stop
是 SIGTERM。
请注意,这SIGKILL
将是一个非常糟糕的选择STOPSIGNAL
,因为无法捕获 KILL 信号。
因此,如果您使用以下行,您的第一个示例应该可以工作:
trap deregister_runner SIGINT SIGQUIT SIGTERM
这样,您的清理功能deregister_runner
将在您发出 adocker stop
或使用Ctrl-C
键绑定时触发(感谢SIGINT
)。
最后,与 和 的问题相关的两个附加Docker
说明bash
:
可以自定义“优雅终止时间”(在停止和终止之间),并且在使用 Bash 入口点时存在一些陷阱(关于“信号传播”)。我在这个 SO 答案中更详细地解释了这两个问题:加速 docker-compose shutdown。
请注意,在许多
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
,它确实包含bash
包:)
推荐阅读
- git - 如何在 Gitlab 中授予对特定 LDAP 用户的访问权限
- powershell - 组合字符串和变量会导致额外的空间
- primefaces - 如何自定义 Primefaces Schedule 的标题
- git - 我可以撤消在其他 git 分支中所做的更改吗?
- hybris - 没有名为 > 'mystoreBrandCategoryCodeValueProvider' 的 bean 可用 (hybris)
- perl - 访问哈希
- regex - 在 RollingFileAppender 中替换 log4j2 文件名中的字符串
- c++ - 如何定义等于 16 字节的类型
- python - 从 python 脚本使用存储在存储帐户中的二进制文件
- javascript - swal 未在 chrome 扩展中呈现