docker 的退出有两种
在docker stop命令执行的时候,会先向容器中PID为1的进程发送系统信号SIGTERM,然后等待容器中的应用程序终止执行,如果等待时间达到设定的超时时间,或者默认的10秒,会继续发送SIGKILL的系统信号强行kill掉进程。在容器中的应用程序,可以选择忽略和不处理SIGTERM信号,不过一旦达到超时时间,程序就会被系统强行kill掉,因为SIGKILL信号是直接发往系统内核的,应用程序没有机会去处理它。在使用docker stop命令的时候,我们唯一能控制的是超时时间,比如设置为20秒超时:
docker stop --time=20 container_name
接着我们来看看docker kill命令,默认情况下,docker kill命令不会给容器中的应用程序有任何gracefully shutdown的机会。它会直接发出SIGKILL的系统信号,以强行终止容器中程序的运行。
在第一种方式docker stop的时候我们的程序有10S中的时间来处理好未处理的事情。 .net core 是用下面的两个事件来处理的 在windows的情况下可以用ctrl+c 来模拟 (直接去点console的X是没有机会处理到它的)
//主要是处理这两个事件
Console.CancelKeyPress += Console_CancelKeyPress;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
//我们可以对cancellationTokenSource进行Cancel
cancellationTokenSource.Cancel()
golang是可以直接接收到这个信号
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
fmt.Println("Program started...")
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM)
s := <-ch
if s == syscall.SIGTERM {
fmt.Println("SIGTERM received!")
//Do something...
}
fmt.Println("Exiting...")
}
如果我们的docker是主要跑在K8s的环境下的话,在k8s里面我们有一个额外的处理方式 preStop