当前位置:   article > 正文

如何优雅的终止 Docker 容器

docker 停止容器

公众号关注 「奇妙的 Linux 世界」

设为「星标」,每天带你玩转 Linux !

227f0aec6acf9f39961e6bbb27e15c2b.jpeg

作为一名系统重启工程师(SRE),你可能经常需要重启容器,毕竟 Kubernetes 的优势就是快速弹性伸缩和故障恢复,遇到问题先重启容器再说,几秒钟即可恢复,实在不行再重启系统,这就是系统重启工程师的杀手锏。然而现实并没有理论上那么美好,某些容器需要花费 10s 左右才能停止,这是为啥?有以下几种可能性:

  1. 容器中的进程没有收到 SIGTERM[1] 信号。

  2. 容器中的进程收到了信号,但忽略了。

  3. 容器中应用的关闭时间确实就是这么长。

对于第 3 种可能性我们无能为力,本文主要解决 1 和 2。

如果要构建一个新的 Docker 镜像,肯定希望镜像越小越好,这样它的下载和启动速度都很快,一般我们都会选择一个瘦了身的操作系统(例如 AlpineBusybox 等)作为基础镜像

33cf60978cec8d67d6d993c60b61239c.png

问题就在这里,这些基础镜像的 init 系统[2]也被抹掉了,这就是问题的根源!

init 系统有以下几个特点:

  • 它是系统的第一个进程,负责产生其他所有用户进程。

  • init 以守护进程方式存在,是所有其他进程的祖先。

  • 它主要负责:

    • 启动守护进程

    • 回收孤儿进程

    • 将操作系统信号转发给子进程

1. Docker 容器停止过程

对于容器来说,init 系统不是必须的,当你通过命令 docker stop mycontainer 来停止容器时,docker CLI 会将 TERM 信号发送给 mycontainer 的 PID 为 1 的进程。

  • 如果 PID 1 是 init 进程 - 那么 PID 1 会将 TERM 信号转发给子进程,然后子进程开始关闭,最后容器终止。

  • 如果没有 init 进程 - 那么容器中的应用进程(Dockerfile 中的 ENTRYPOINT 或 CMD 指定的应用)就是 PID 1,应用进程直接负责响应 TERM 信号。这时又分为两种情况:

    • 应用不处理 SIGTERM - 如果应用没有监听 SIGTERM 信号,或者应用中没有实现处理 SIGTERM 信号的逻辑,应用就不会停止,容器也不会终止。

    • 容器停止时间很长 - 运行命令 docker stop mycontainer 之后,Docker 会等待 10s,如果 10s 后容器还没有终止,Docker 就会绕过容器应用直接向内核发送 SIGKILL,内核会强行杀死应用,从而终止容器。

2. 容器进程收不到 SIGTERM 信号?

如果容器中的进程没有收到 SIGTERM 信号,很有可能是因为应用进程不是 PID 1,PID 1 是 shell,而应用进程只是 shell 的子进程。而 shell 不具备 init 系统的功能,也就不会将操作系统的信号转发到子进程上,这也是容器中的应用没有收到 SIGTERM 信号的常见原因。

问题的根源就来自 Dockerfile,例如:

  1. FROM alpine:3.7
  2. COPY popcorn.sh .
  3. RUN chmod +x popcorn.sh
  4. ENTRYPOINT ./popcorn.sh

ENTRYPOINT 指令使用的是 shell 模式[3],这样 Docker 就会把应用放到 shell 中运行,因此 shell 是 PID 1。

解决方案有以下几种:

方案 1:使用 exec 模式的 ENTRYPOINT 指令

与其使用 shell 模式,不如使用 exec 模式[4],例如:

  1. FROM alpine:3.7
  2. COPY popcorn.sh .
  3. RUN chmod +x popcorn.sh
  4. ENTRYPOINT ["./popcorn.sh"]

这样 PID 1 就是 ./popcorn.sh,它将负责响应所有发送到容器的信号,至于 ./popcorn.sh 是否真的能捕捉到系统信号,那是另一回事。

举个例子,假设使用上面的 Dockerfile 来构建镜像,popcorn.sh 脚本每过一秒打印一次日期:

  1. #!/bin/sh
  2. while true
  3. do
  4.     date
  5.     sleep 1
  6. done

构建镜像并创建容器:

  1. 声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/602391
    推荐阅读
    相关标签