diff --git a/actions/update.go b/actions/update.go index b41d34c..2910756 100644 --- a/actions/update.go +++ b/actions/update.go @@ -67,6 +67,8 @@ func Update(client container.Client, names []string, cleanup bool, noRestart boo continue } + container.WasRunning = container.IsRunning() + if container.Stale { if err := client.StopContainer(container, waitTime); err != nil { log.Error(err) diff --git a/container/client.go b/container/client.go index afa9a33..723d261 100644 --- a/container/client.go +++ b/container/client.go @@ -37,31 +37,41 @@ type Client interface { // * DOCKER_HOST the docker-engine host to send api requests to // * DOCKER_TLS_VERIFY whether to verify tls certificates // * DOCKER_API_VERSION the minimum docker api version to work with -func NewClient(pullImages, enableLabel bool) Client { +func NewClient(pullImages, enableLabel bool, checkAll bool) Client { cli, err := dockerclient.NewEnvClient() if err != nil { log.Fatalf("Error instantiating Docker client: %s", err) } - return dockerClient{api: cli, pullImages: pullImages, enableLabel: enableLabel} + return dockerClient{ + api: cli, + pullImages: pullImages, + enableLabel: enableLabel, + checkAll: checkAll} } type dockerClient struct { api *dockerclient.Client pullImages bool enableLabel bool + checkAll bool } func (client dockerClient) ListContainers(fn Filter) ([]Container, error) { cs := []Container{} bg := context.Background() - log.Debug("Retrieving running containers") + if client.checkAll { + log.Debug("Retrieving containers") + } else { + log.Debug("Retrieving running containers") + } runningContainers, err := client.api.ContainerList( bg, - types.ContainerListOptions{}) + types.ContainerListOptions{ + All: client.checkAll}) if err != nil { return nil, err } @@ -103,10 +113,12 @@ func (client dockerClient) StopContainer(c Container, timeout time.Duration) err signal = defaultStopSignal } - log.Infof("Stopping %s (%s) with %s", c.Name(), c.ID(), signal) + if c.WasRunning { + log.Infof("Stopping %s (%s) with %s", c.Name(), c.ID(), signal) - if err := client.api.ContainerKill(bg, c.ID(), signal); err != nil { - return err + if err := client.api.ContainerKill(bg, c.ID(), signal); err != nil { + return err + } } // Wait for container to exit, but proceed anyway after the timeout elapses @@ -173,11 +185,13 @@ func (client dockerClient) StartContainer(c Container) error { } - log.Debugf("Starting container %s (%s)", name, creation.ID) + if c.WasRunning { + log.Debugf("Starting container %s (%s)", name, creation.ID) - err = client.api.ContainerStart(bg, creation.ID, types.ContainerStartOptions{}) - if err != nil { - return err + err = client.api.ContainerStart(bg, creation.ID, types.ContainerStartOptions{}) + if err != nil { + return err + } } return nil diff --git a/container/container.go b/container/container.go index e620d92..ad5409a 100644 --- a/container/container.go +++ b/container/container.go @@ -27,7 +27,8 @@ func NewContainer(containerInfo *types.ContainerJSON, imageInfo *types.ImageInsp // Container represents a running Docker container. type Container struct { - Stale bool + Stale bool + WasRunning bool containerInfo *types.ContainerJSON imageInfo *types.ImageInspect @@ -106,6 +107,13 @@ func (c Container) IsWatchtower() bool { return ok && val == "true" } +// IsRunning returns a boolean flag indicating whether or not the current +// container is running. The status is determined by the value of the +// container's "State.Running" property. +func (c Container) IsRunning() bool { + return c.containerInfo.State.Running +} + // StopSignal returns the custom stop signal (if any) that is encoded in the // container's metadata. If the container has not specified a custom stop // signal, the empty string "" is returned. diff --git a/main.go b/main.go index 1fd015b..a77cd7f 100644 --- a/main.go +++ b/main.go @@ -61,6 +61,11 @@ func main() { Usage: "the cron expression which defines when to update", EnvVar: "WATCHTOWER_SCHEDULE", }, + cli.BoolFlag{ + Name: "check-all", + Usage: "check non-running containers", + EnvVar: "WATCHTOWER_CHECK_ALL", + }, cli.BoolFlag{ Name: "no-pull", Usage: "do not pull new images", @@ -159,7 +164,7 @@ func before(c *cli.Context) error { return err } - client = container.NewClient(!c.GlobalBool("no-pull"), c.GlobalBool("label-enable")) + client = container.NewClient(!c.GlobalBool("no-pull"), c.GlobalBool("label-enable"), c.GlobalBool("check-all")) notifier = notifications.NewNotifier(c) return nil