From de2ac9341d582546820b54fa6326b0de90c14533 Mon Sep 17 00:00:00 2001 From: Kaleb Elwert Date: Tue, 17 Oct 2017 06:53:30 +0200 Subject: [PATCH] Add a method of enabling or disabling containers using labels Switch command line flag from no-enable to label-enable and simplify logic Add basic documentation for the --label-enable flag --- README.md | 17 +++++++++++++++++ container/client.go | 19 +++++++++++++++---- container/container.go | 18 ++++++++++++++++++ main.go | 7 ++++++- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0d263b4..9edffa1 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ docker run --rm v2tec/watchtower --help * `--interval, -i` Poll interval (in seconds). This value controls how frequently watchtower will poll for new images. Defaults to 300 seconds (5 minutes). * `--schedule, -s` [Cron expression](https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format) which defines when and how often to check for new images. Either `--interval` or the schedule expression could be defined, but not both. * `--no-pull` Do not pull new images. When this flag is specified, watchtower will not attempt to pull new images from the registry. Instead it will only monitor the local image cache for changes. Use this option if you are building new images directly on the Docker host without pushing them to a registry. +* `--label-enable` Watch containers where the `com.centurylinklabs.watchtower.enable` label is set to true. * `--cleanup` Remove old images after updating. When this flag is specified, watchtower will remove the old image after restarting a container with a new image. Use this option to prevent the accumulation of orphaned images on your system as containers are updated. * `--tlsverify` Use TLS when connecting to the Docker socket and verify the server's certificate. * `--debug` Enable debug mode. When this option is specified you'll see more verbose logging in the watchtower log file. @@ -123,6 +124,22 @@ Or, it can be specified as part of the `docker run` command line: docker run -d --label=com.centurylinklabs.watchtower.stop-signal=SIGHUP someimage ``` +## Selectively Watching Containers + +By default, watchtower will watch all containers. +However, sometimes only some containers should be updated. +If you need to selectively watch containers, pass the --label-enable flag on startup and set the *com.centurylinklabs.watchtower.enable* label with a value of true for the containers you want to watch. + +```docker +LABEL com.centurylinklabs.watchtower.enable="true" +``` + +Or, it can be specified as part of the `docker run` command line: + +```bash +docker run -d --label=com.centurylinklabs.watchtower.enable=true someimage +``` + ## Remote Hosts By default, watchtower is set-up to monitor the local Docker daemon (the same daemon running the watchtower container itself). However, it is possible to configure watchtower to monitor a remote Docker endpoint. When starting the watchtower container you can specify a remote Docker endpoint with either the `--host` flag or the `DOCKER_HOST` environment variable: diff --git a/container/client.go b/container/client.go index fb94071..afa9a33 100644 --- a/container/client.go +++ b/container/client.go @@ -37,19 +37,20 @@ 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 bool) Client { +func NewClient(pullImages, enableLabel bool) Client { cli, err := dockerclient.NewEnvClient() if err != nil { log.Fatalf("Error instantiating Docker client: %s", err) } - return dockerClient{api: cli, pullImages: pullImages} + return dockerClient{api: cli, pullImages: pullImages, enableLabel: enableLabel} } type dockerClient struct { - api *dockerclient.Client - pullImages bool + api *dockerclient.Client + pullImages bool + enableLabel bool } func (client dockerClient) ListContainers(fn Filter) ([]Container, error) { @@ -77,6 +78,16 @@ func (client dockerClient) ListContainers(fn Filter) ([]Container, error) { } c := Container{containerInfo: &containerInfo, imageInfo: &imageInfo} + + if client.enableLabel { + // If label filtering is enabled, containers should only be enabled + // if the label is specifically set to true. + enabledLabel, ok := c.Enabled() + if !ok || !enabledLabel { + continue + } + } + if fn(c) { cs = append(cs, c) } diff --git a/container/container.go b/container/container.go index c49da33..e620d92 100644 --- a/container/container.go +++ b/container/container.go @@ -2,6 +2,7 @@ package container import ( "fmt" + "strconv" "strings" "github.com/docker/docker/api/types" @@ -11,6 +12,7 @@ import ( const ( watchtowerLabel = "com.centurylinklabs.watchtower" signalLabel = "com.centurylinklabs.watchtower.stop-signal" + enableLabel = "com.centurylinklabs.watchtower.enable" zodiacLabel = "com.centurylinklabs.zodiac.original-image" ) @@ -64,6 +66,22 @@ func (c Container) ImageName() string { return imageName } +// Enabled returns the value of the container enabled label and if the label +// was set. +func (c Container) Enabled() (bool, bool) { + rawBool, ok := c.containerInfo.Config.Labels[enableLabel] + if !ok { + return false, false + } + + parsedBool, err := strconv.ParseBool(rawBool) + if err != nil { + return false, false + } + + return parsedBool, true +} + // Links returns a list containing the names of all the containers to which // this container is linked. func (c Container) Links() []string { diff --git a/main.go b/main.go index 0cf3465..b359fba 100644 --- a/main.go +++ b/main.go @@ -79,6 +79,11 @@ func main() { Usage: "use TLS and verify the remote", EnvVar: "DOCKER_TLS_VERIFY", }, + cli.BoolFlag{ + Name: "label-enable", + Usage: "watch containers where the com.centurylinklabs.watchtower.enable label is true", + EnvVar: "WATCHTOWER_LABEL_ENABLE", + }, cli.BoolFlag{ Name: "debug", Usage: "enable debug mode with verbose logging", @@ -146,7 +151,7 @@ func before(c *cli.Context) error { return err } - client = container.NewClient(!c.GlobalBool("no-pull")) + client = container.NewClient(!c.GlobalBool("no-pull"), c.GlobalBool("label-enable")) notifier = notifications.NewNotifier(c) return nil