docker容器如何优雅的终止详解

更新时间:2023-06-07 20:40:12 阅读: 评论:0

docker容器如何优雅的终⽌详解
前⾔
在Docker⼤⾏其道的今天,我们能够⾮常⽅便的使⽤容器打包我们的应⽤程序,并且将它在我们的服务器上部署并运⾏起来。但是,谈论到如何停掉运⾏中的docker容器并正确的终⽌其中的程序,这就成为⼀个⾮常值得讨论的话题了。berze
事实上,在我们⽇常的项⽬当中,这是我们经常需要⾯对和处理的问题:
场景A:假如我们打包在容器中的程序,提供HTTP⽅式的服务,负责处理各种HTTP requests并返回结果,我们必然希望在容器被停掉的时候,能够让程序有时间把已经在处理中的请求继续处理完毕,并返回结果给客户端。
场景B:⼜⽐如我们打包在容器中的程序,负责写⼊数据到某个数据⽂件中,我们希望程序能够在容器被停掉的时候,有时间把内存中缓存的数据持久化到存储设备中,以防数据丢失。
场景C:再⽐如现在流⾏的微服务架构中,⼀般会有服务发现的机制,也即每⼀个微服务在启动之后,都会主动把⾃⼰的地址信息注册到服务发现模块当中,让其他的服务可以知道⾃⼰的存在。⽽在容器被停掉的时候,微服务需要即时从服务发现模块中注销⾃⼰,以防⽌从API Gateway⽽来的请求被错误的
路由到了已经被停⽌掉的微服务。
如上的各种场景中,都要求打包在容器中的应⽤程序能够被优雅的终⽌(也即gracefully shutdown),这种gracefully shutdown 的⽅式,允许程序在容器被停⽌的时候,有⼀定时间做⼀些后续处理操作,这也是我们需要进⼀步探讨的话题。
docker stop 与 docker kill 的区别
weedsDocker本⾝提供了两种终⽌容器运⾏的⽅式,即docker stop与docker kill。
docker stop
先来说说docker stop吧,当我们⽤docker stop命令来停掉容器的时候,docker默认会允许容器中的应⽤程序有10秒的时间⽤以终⽌运⾏。所以我们查看docker stop命令帮助的时候,会有如下的提⽰:
→ docker stop --help
宜昌英语辅导班Usage: docker stop [OPTIONS] CONTAINER []
Stop one or more running containers
Options:
--help  Print usage
-t, --time int Seconds to wait for stop before killing it (default 10)
在docker stop命令执⾏的时候,会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应⽤程序终⽌执⾏,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强⾏kill掉进程。在容器中的应⽤程序,可以选择忽略和不处理SIGTERM信号,不过⼀旦达到超时时间,程序就会被系统强⾏kill掉,因为SIGKILL信号是直接发往系统内核的,应⽤程序没有机会去处理它。在使⽤docker stop命令的时候,我们唯⼀能控制的是超时时间,⽐如设置为20秒超时:
docker stop --time=20 container_name
docker kill
接着我们来看看docker kill命令,默认情况下,docker kill命令不会给容器中的应⽤程序有任何gracefully shutdown的机会。它会直接发出SIGKILL的系统信号,以强⾏终⽌容器中程序的运⾏。通过查看docker kill命令的帮助,我们可以看到,除了默认发送SIGKILL信号外,还允许我们发送⼀些⾃
定义的系统信号:
→ docker kill --help
furthermore翻译Usage: docker kill [OPTIONS] CONTAINER []
Kill one or more running containers
Options:
--help  Print usage
-s, --signal string Signal to nd to the container (default "KILL")
⽐如,如果我们想向docker中的程序发送SIGINT信号,我们可以这样来实现:
docker kill --signal=SIGINT container_name
与docker stop命令不⼀样的地⽅在于,docker kill没有任何的超时时间设置,它会直接发送SIGKILL信号,以及⽤户通过signal 参数指定的其他信号。
其实不难看出,docker stop命令,更类似于Linux系统中的kill命令,⼆者都是发送系统信号SIGTERM。⽽docker kill命令,更像是Linux系统中的kill -9或者是kill -SIGKILL命令,⽤来发送SIGKILL信号,强⾏终⽌进程。
在程序中接收并处理信号
了解了docker stop与docker kill的区别,我们能够知道,docker kill适合⽤来强⾏终⽌程序并实现快速停⽌容器。⽽如果希望程序能够gracefully shutdown的话,docker stop才是不⼆之选。这样,我们可以让程序在接收到SIGTERM信号后,有⼀定的时间处理、保存程序执⾏现场,优雅的退出程序。
接下来我们可以写⼀个简单的Go程序来实现信号的接收与处理,程序在启动过后,会⼀直阻塞并监听系统信号,直到监测到对应的系统信号后,输出控制台并退出执⾏。
//
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
四世同堂英文func main() {
fmt.Println("")
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM)
s := <-ch
if s == syscall.SIGTERM {
fmt.Println("SIGTERM received!")
/
sylar
/
}
fmt.Println("")
}
接下来使⽤交叉编译的⽅式来编译程序,让程序可以在Linux下运⾏:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o graceful
编译好之后,我们还需要打包程序到容器中运⾏。于是,我们还得有个Dockerfile。在这⾥,我们选择使⽤体积⼩⼜轻盈的alpine镜像作为基础镜像,打包这个Go程序:
from alpine:latest
MAINTAINER Timothy
ADD graceful /graceful
CMD ["/graceful"]
这⾥需要避开的⼀个坑,是Dockerfile中CMD命令的⽤法。
CMD命令有两种⽅式:
CMD /graceful
使⽤CMD command param1 param2 这种⽅式,其实是以shell的⽅式运⾏程序。最终程序被执⾏时,类似于/bin/sh -c的⽅式运⾏了我们的程序,这样会导致/bin/sh以PID为1的进程运⾏,⽽我们的程序只不过是它fork/execs出来的⼦进程⽽已。前⾯我们提到过docker stop的SIGTERM信号只是发送给容器中PID为1的进程,⽽这样,我们的程序就没法接收和处理到信号了。
CMD [“/graceful”]
pretended使⽤CMD [“executable”,”param1”,”param2”] 这种⽅式启动程序,才是我们想要的,这种⽅式执⾏和启动时,我们的程序会被直接启动执⾏,⽽不是以shell的⽅式,这样我们的程序就能以PID=1的⽅式开始执⾏了。
话题转回来,我们开始执⾏容器构建操作,打包程序:
docker build -t registry.xiaozhou/graceful:latest .airport是什么意思
我爱你用韩语怎么说打包过后的镜像,才6MB左右:
λ Timothy [workspace/src/graceful] → docker images
REPOSITORY            TAG    IMAGE ID  CREATED    SIZE
registry.xiaozhou/graceful      latest    b2210a85ca55  20 hours ago  6.484 MB
启动并运⾏容器:
λ Timothy [workspace/src/graceful] → docker run -d --name graceful b2210a85
查看容器运⾏状态:
λ Timothy [workspace/src/graceful] → docker ps -a
CONTAINER ID  IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
fd18eedafd16  b221    "/graceful"  3 conds ago  Up 2 conds      graceful
查看容器输出,能看到程序已经正常启动:
λ Timothy [workspace/src/graceful] → docker logs graceful
<
接着我们要使⽤docker stop⼤法,看程序能否响应SIGTERM信号:
λ Timothy [workspace/src/graceful] → docker stop graceful
graceful
最后,查看容器的⽇志,检验输出:
λ Timothy [workspace/src/graceful] → docker logs graceful
<
SIGTERM received!
bocog<
总结
以上就是这篇⽂章的全部内容了,⽤docker kill命令,可以简单粗暴的终⽌docker容器中运⾏的程序,但是想要优雅的终⽌掉的话,我们需要使⽤docker stop命令,并且在程序中多花⼀些功夫来处理系统信号,这样能保证程序不被粗暴的终⽌掉,从⽽实现gracefully shutdown。希望本⽂的内容对⼤家的学习或者⼯作能有所帮助,如果有疑问⼤家可以留⾔交流。

本文发布于:2023-06-07 20:40:12,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/896805.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:程序   信号   容器   处理   系统   服务   时间   命令
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图