看moby的源码,restartmanager/restartmanager.go的ShouldRestart函数中有这样的逻辑:根据restart参数的设置值确定在各种情况下是否应该重启,并返回判断结果:
var restart bool
switch {
case rm.policy.IsAlways():
restart = true
case rm.policy.IsUnlessStopped() && !hasBeenManuallyStopped:
restart = true
case rm.policy.IsOnFailure():
// the default value of 0 for MaximumRetryCount means that we will not enforce a maximum count
if max := rm.policy.MaximumRetryCount; max == 0 || rm.restartCount < max {
restart = exitCode != 0
}
}
而在daemon/monitor.go的ProcessEvent函数中使用了ShouldRestart的逻辑。docker的daemon进程会监听各个容器生命周期中各种事件,而对应的行为是通过调用ProcessEvent来处理的,只要有事件触发,那么libcontainerd就会调用ProcessEvent函数生成行为。当判断事件是容器退出事件时,就会根据传入的restart police来处理这个事件:
case libcontainerdtypes.EventExit:
if int(ei.Pid) == c.Pid {
// ... 此处省略15行
restart, wait, err := c.RestartManager().ShouldRestart(ei.ExitCode, daemon.IsShuttingDown() || c.HasBeenManuallyStopped, time.Since(c.StartedAt))
if err == nil && restart {
c.RestartCount++
c.SetRestarting(&exitStatus)
} else {
if ei.Error != nil {
c.SetError(ei.Error)
}
c.SetStopped(&exitStatus)
defer daemon.autoRemove(c)
}
而具体moby定义了哪些事件呢?在libcontainerd/types/types.go中定义了如下事件:
// Event constants used when reporting events
const (
EventUnknown EventType = "unknown"
EventExit EventType = "exit"
EventOOM EventType = "oom"
EventCreate EventType = "create"
EventStart EventType = "start"
EventExecAdded EventType = "exec-added"
EventExecStarted EventType = "exec-started"
EventPaused EventType = "paused"
EventResumed EventType = "resumed"
)
每一个事件信息量都是一个复合变量struct,包含了容器ID、容器进程ID、Pid、退出代码、退出时间、是否OOM掉了,以及详细的err对象。这里包含的信息足够使docker engine对涉事容器进行操作了。
// EventInfo contains the event info
type EventInfo struct {
ContainerID string
ProcessID string
Pid uint32
ExitCode uint32
ExitedAt time.Time
OOMKilled bool
Error error
}