crond 的“docker stop”超时

Ste*_*lly 6 cron docker

我试图理解为什么我的 Docker 容器没有正常停止并且只是超时。容器正在运行crond

FROM alpine:latest

ADD crontab /etc/crontabs/root
RUN chmod 0644 /etc/crontabs/root

CMD ["crond", "-f"]
Run Code Online (Sandbox Code Playgroud)

crontab文件是:

* * * * * echo 'Working'
# this empty line required by cron
Run Code Online (Sandbox Code Playgroud)

内置docker build . -t periodic:latest

并运行docker run --rm --name periodic periodic:latest

这一切都很好,但是当我尝试docker stop periodic从另一个终端进行操作时,它不会优雅地停止,超时会突然终止。就像crond没有响应 SIGTERM 一样。

crond肯定是PID 1

/ # ps
PID   USER     TIME  COMMAND
    1 root      0:00 crond -f
    6 root      0:00 ash
   11 root      0:00 ps
Run Code Online (Sandbox Code Playgroud)

但是,如果我这样做:

docker run -it --rm --name shell alpine:latest ashdocker exec -it shell crond -f另一个终端中,我可以使用crondSIGTERM 从第一个 shell 中终止,所以我知道可以使用 SIGTERM 停止它。

谢谢你的帮助。

Ste*_*lly 6

向容器添加一个 init 进程(init: truein docker-compose.yml)解决了这个问题。

\n

编辑:我阅读了此https://blog.thesparktree.com/cron-in-docker以了解在 Docker 中运行 cron 的问题和解决方案。从这篇文章:

\n

“最后,当你\xe2\x80\x99一直在玩的时候,你可能已经注意到\xe2\x80\x99很难杀死运行cron的容器。你可能必须使用dockerkill或docker-composekill来终止容器,而不是使用 ctrl + C 或 docker stop。

\n

不幸的是,在前台运行时,cron 实现似乎并不总是正确处理 SIGINT。

\n

在研究了几种替代方案后,唯一可行的解​​决方案似乎是使用进程管理器(如 tini 或 s6-overlay)。由于 tini 已合并到 Docker 1.13 中,从技术上讲,您可以通过将 --init 传递给 docker run 命令来透明地使用它。在实践中,您通常可以\xe2\x80\x99t,因为您的集群管理器\xe2\x80\x99t不支持它。”

\n

自从我最初的帖子和答案以来,我已经迁移到 Kubernetes,所以init在 docker-compose.yml 中将不起作用。我的容器基于 Debian Buster,所以我现在已经安装tini在 Dockerfile 中,并将 ENTRYPOINT 更改为["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"](我的 entrypoint.sh 最终做到了exec cron -f

\n

  • cron 有什么特别之处,它需要 init: true 才能优雅地停止?有没有办法让镜像/容器本身解决问题,而不需要更改 docker-compose? (2认同)