深圳有没有什么网站/山西seo
通过docker的API或者docker event命令,我们都可以获取到容器生命周期内发生了那些事情。首先把结论放出来,然后在看实现过程。
这个是实验的结论,那我怎么获取到这些状态和事件的呢?很简单,就是通过上面的api watch。
通过docker go client很容易实现
func (w *watcher) watch() {filters := filters.NewArgs()filters.Add("type", "container")options := types.EventsOptions{Since: fmt.Sprintf("%d", w.lastValidTimestamp),Filters: filters,}for {events, errors := w.client.Events(w.ctx, options)WATCH:for {select {case event := <-events:fmt.Printf("get event %v action %v \n",event.Actor.Attributes["name"],event.Action)logp.Debug("docker", "Got a new docker event: %v", event)w.lastValidTimestamp = event.Time// Add / updateif event.Action == "create" || event.Action == "update" {name := event.Actor.Attributes["name"]image := event.Actor.Attributes["image"]delete(event.Actor.Attributes, "name")delete(event.Actor.Attributes, "image")container := &Container{ID: event.Actor.ID,Name: name,Image: image,Labels: event.Actor.Attributes,Env: make(map[string]string),}info, err := w.client.ContainerInspect(w.ctx, event.Actor.ID)if err == nil {for _, env := range info.Config.Env {kv := strings.SplitN(env, "=", 2)if len(kv) >= 2 {container.Env[kv[0]] = kv[1]}}}w.containers[container.ID] = containerw.containers[container.Name] = container}// Deleteif event.Action == "die" || event.Action == "kill" {delete(w.containers, event.Actor.ID)delete(w.containers, event.Actor.Attributes["name"])}case err := <-errors:// Restart watch calllogp.Err("Error watching for docker events: %v", err)time.Sleep(1 * time.Second)break WATCHcase <-w.ctx.Done():logp.Debug("docker", "Watcher stopped")return}}}
}
这样当我们操作docker上的时候就能顺利的获取到它的状态,譬如一次docker run操作,
get event big_meninsky action create
get event big_meninsky action start
相应的一次stop操作就可以获取到
get event big_meninsky action kill
get event big_meninsky action kill
get event big_meninsky action die
get event big_meninsky action stop
这里有个很有意思的事,就是怎么会有两次kill操作呢!那是因为,docker stop命令的玩法
docker stop: Stop a running container (send SIGTERM, and then SIGKILL after grace period)
就是先发现TERM信号(为了让容器优雅关闭),再发送KILL信号。所以收到两次kill event命令。这个和kill最大的区别,它是直接发送KILL信号,所以不会有两次kill event。