diff --git a/shared/docker/docker.go b/shared/docker/docker.go index 29ed1061..7bc2ed07 100644 --- a/shared/docker/docker.go +++ b/shared/docker/docker.go @@ -1,9 +1,11 @@ package docker import ( + "errors" "io" "io/ioutil" + log "github.com/Sirupsen/logrus" "github.com/samalba/dockerclient" ) @@ -80,24 +82,48 @@ func Wait(client dockerclient.Client, name string) (*dockerclient.ContainerInfo, errc := make(chan error, 1) infoc := make(chan *dockerclient.ContainerInfo, 1) go func() { - - // blocks and waits for the container to finish - // by streaming the logs (to /dev/null). Ideally - // we could use the `wait` function instead - rc, err := client.ContainerLogs(name, LogOptsTail) - if err != nil { - errc <- err - return + // options to fetch the stdout and stderr logs + // by tailing the output. + logOptsTail := &dockerclient.LogOptions{ + Follow: true, + Stdout: true, + Stderr: true, } - io.Copy(ioutil.Discard, rc) - rc.Close() - info, err := client.InspectContainer(name) - if err != nil { - errc <- err - return + for attempts := 0; attempts < 5; attempts++ { + if attempts > 0 { + // When resuming the stream, only grab the last line when starting + // the tailing. + logOptsTail.Tail = 1 + } + + // blocks and waits for the container to finish + // by streaming the logs (to /dev/null). Ideally + // we could use the `wait` function instead + rc, err := client.ContainerLogs(name, logOptsTail) + if err != nil { + errc <- err + return + } + io.Copy(ioutil.Discard, rc) + rc.Close() + + info, err := client.InspectContainer(name) + if err != nil { + errc <- err + return + } + + if !info.State.Running { + // The container is no longer running, there should be no more logs to tail. + infoc <- info + return + } + + log.Debugf("Attempting to resume log tailing after %d attempts.\n", attempts) } - infoc <- info + + errc <- errors.New("Maximum number of attempts made while tailing logs.") }() select {