关于docker容器优雅退出的问题详解
前言
最近因为工作的原因,谈到了关于如何正确的退出运行中的docker容器,这是一个非常值得讨论的话题了。本文将给出详细的介绍,下面来一起看看吧。
容器信号使用
我们跑在容器中的程序通常想在容器退出之前做一些清理操作,比较常用的方式是监听一个信号,延迟关闭容器。
docker提供了这样的功能:
╰─➤dockerstop--help Usage:dockerstop[OPTIONS]CONTAINER[CONTAINER...] Stoponeormorerunningcontainers Options: --helpPrintusage -t,--timeintSecondstowaitforstopbeforekillingit(default10)
docker1.13以上版本在创建容器时可直接指定STOP_TIMEOUT和STOP_SIGNAL参数:
$dockerrun--help ... --stop-signalstringSignaltostopacontainer,SIGTERMbydefault(default"SIGTERM") --stop-timeoutintTimeout(inseconds)tostopacontainer ...
但是。。。
我们测试一个:
packagemain import( "fmt" "os" "os/signal" "syscall" "time" ) funcmain(){ fmt.Println("signaltest") gofunc(){ for{ c:=make(chanos.Signal,1) signal.Notify(c,syscall.SIGTERM) s:=<-c fmt.Println("Gotsignal:",s) } }() time.Sleep(time.Second*100) }
Dockerfile:
FROMgolang:1.8.0 COPYmain.go. RUNgobuild-osignal&&cpsignal$GOPATH/bin CMDsignal
构建:
dockerbuild-tsignal:latest.
运行:
dockerrun--namesignalsignal:latest
再开一终端,运行:
dockerstop-t10signal
发现并没有打印出Gotsignal:...监听信号失败。
问题再于:我们dockerinspectsignal看一下
可以看到
Path:/bin/sh Args:[ -c, signal ]
或者dockerexecsignalps看一下可以看到pid为1的进程并不是signal,而是shell.
所以原因找到了,是因为dockerengine只给pid为1的进程发送信号,sh收到了信号而我们想要的signal进程没有收到信号
解决办法:
FROMgolang:1.8.0 COPYmain.go. RUNgobuild-osignal&&cpsignal$GOPATH/bin CMD["signal"]#不能写成CMDsignal,这会直接exec,否则会以shell的方式派生子进程。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。