diff --git a/daemon/monitor.go b/daemon/monitor.go index 0a82c5f8fd..f9f7def98d 100644 --- a/daemon/monitor.go +++ b/daemon/monitor.go @@ -77,6 +77,7 @@ func (daemon *Daemon) StateChanged(id string, e libcontainerd.StateInfo) error { c.Reset(false) return err } + daemon.LogContainerEvent(c, "start") case libcontainerd.StatePause: c.Paused = true daemon.LogContainerEvent(c, "pause") diff --git a/daemon/start.go b/daemon/start.go index 52531f511e..1b34f42692 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -131,7 +131,6 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error) return err } - defer daemon.LogContainerEvent(container, "start") // this is logged even on error if err := daemon.containerd.Create(container.ID, *spec, libcontainerd.WithRestartManager(container.RestartManager(true))); err != nil { // if we receive an internal error from the initial start of a container then lets // return it instead of entering the restart loop @@ -149,6 +148,9 @@ func (daemon *Daemon) containerStart(container *container.Container) (err error) } container.Reset(false) + + // start event is logged even on error + daemon.LogContainerEvent(container, "start") return err } diff --git a/integration-cli/docker_cli_events_test.go b/integration-cli/docker_cli_events_test.go index f426650c2b..f17b711cc2 100644 --- a/integration-cli/docker_cli_events_test.go +++ b/integration-cli/docker_cli_events_test.go @@ -604,3 +604,44 @@ func (s *DockerSuite) TestEventsFilterImageInContainerAction(c *check.C) { events := strings.Split(strings.TrimSpace(out), "\n") c.Assert(len(events), checker.GreaterThan, 1, check.Commentf(out)) } + +func (s *DockerSuite) TestEventsContainerRestart(c *check.C) { + dockerCmd(c, "run", "-d", "--name=testEvent", "--restart=on-failure:3", "busybox", "false") + + // wait until test2 is auto removed. + waitTime := 10 * time.Second + if daemonPlatform == "windows" { + // nslookup isn't present in Windows busybox. Is built-in. + waitTime = 90 * time.Second + } + + err := waitInspect("testEvent", "{{ .State.Restarting }} {{ .State.Running }}", "false false", waitTime) + c.Assert(err, checker.IsNil) + + var ( + createCount int + startCount int + dieCount int + ) + out, _ := dockerCmd(c, "events", "--since=0", fmt.Sprintf("--until=%d", daemonTime(c).Unix()), "-f", "container=testEvent") + events := strings.Split(strings.TrimSpace(out), "\n") + + nEvents := len(events) + c.Assert(nEvents, checker.GreaterOrEqualThan, 1) //Missing expected event + actions := eventActionsByIDAndType(c, events, "testEvent", "container") + + for _, a := range actions { + switch a { + case "create": + createCount++ + case "start": + startCount++ + case "die": + dieCount++ + } + } + c.Assert(createCount, checker.Equals, 1, check.Commentf("testEvent should be created 1 times: %v", actions)) + c.Assert(startCount, checker.Equals, 4, check.Commentf("testEvent should start 4 times: %v", actions)) + c.Assert(dieCount, checker.Equals, 4, check.Commentf("testEvent should die 4 times: %v", actions)) + +}