mirror of
https://github.com/containrrr/watchtower.git
synced 2025-09-22 05:40:50 +02:00
Merge branch 'master' into net
This commit is contained in:
commit
db473821f6
15 changed files with 329 additions and 105 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1,3 @@
|
|||
watchtower
|
||||
vendor
|
||||
.glide
|
|
@ -16,21 +16,9 @@ cd watchtower
|
|||
## Building and testing
|
||||
watchtower is a go application and is built with go commands. The following commands assume that you are at the root level of your repo.
|
||||
```bash
|
||||
go get ./... # analyzes and retrieves package dependencies
|
||||
go build # compiles and packages an executable binary, watchtower
|
||||
go test # runs tests
|
||||
./watchtower # runs the application (outside of a container)
|
||||
go get -u github.com/Masterminds/glide # installs glide for vendoring
|
||||
glide install # retrieves package dependencies
|
||||
go build # compiles and packages an executable binary, watchtower
|
||||
go test # runs tests
|
||||
./watchtower # runs the application (outside of a container)
|
||||
```
|
||||
|
||||
### Building the docker image
|
||||
watchtower is packaged and distributed as a docker image. A [golang-builder](https://github.com/CenturyLinkLabs/golang-builder) is used to package the go code and its
|
||||
dependencies as a minimally-sized application. The application binary is then layered into to a minimal docker image (see `Dockerfile`), so that the entire image is <10MB.
|
||||
See `circle.yml` for further details.The following commands assume that you are at the root level of your repo (i.e. `watchtower/`).
|
||||
|
||||
```bash
|
||||
docker pull centurylink/golang-builder:latest # download the builder
|
||||
docker run -v $(pwd):/src centurylink/golang-builder:latest # build the minimal binary
|
||||
docker build -t <yourfork>/watchtower:latest . # build the docker image
|
||||
docker run -v /var/run/docker.sock:/var/run/docker.sock <yourfork>/watchtower # run the application (inside of a container)
|
||||
```
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
FROM centurylink/ca-certs
|
||||
MAINTAINER CenturyLink Labs <innovationslab@ctl.io>
|
||||
LABEL "com.centurylinklabs.watchtower"="true"
|
||||
|
||||
COPY watchtower /
|
||||
ENTRYPOINT ["/watchtower"]
|
|
@ -186,7 +186,7 @@
|
|||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2015 CenturyLink
|
||||
Copyright 2015 Watchtower contributors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
27
README.md
27
README.md
|
@ -1,9 +1,7 @@
|
|||
# Watchtower
|
||||

|
||||
|
||||
[](https://circleci.com/gh/CenturyLinkLabs/watchtower)
|
||||
[](https://godoc.org/github.com/CenturyLinkLabs/watchtower)
|
||||
[](https://imagelayers.io/?images=centurylink/watchtower:latest 'Get your own badge on imagelayers.io')
|
||||
[](https://circleci.com/gh/v2tec/watchtower)
|
||||
[](https://godoc.org/github.com/v2tec/watchtower)
|
||||
[](https://microbadger.com/images/v2tec/watchtower "Get your own image badge on microbadger.com")
|
||||
|
||||
A process for watching your Docker containers and automatically restarting them whenever their base image is refreshed.
|
||||
|
||||
|
@ -19,14 +17,14 @@ For example, let's say you were running watchtower along with an instance of *ce
|
|||
$ docker ps
|
||||
CONTAINER ID IMAGE STATUS PORTS NAMES
|
||||
967848166a45 centurylink/wetty-cli Up 10 minutes 0.0.0.0:8080->3000/tcp wetty
|
||||
6cc4d2a9d1a5 centurylink/watchtower Up 15 minutes watchtower
|
||||
6cc4d2a9d1a5 v2tec/watchtower Up 15 minutes watchtower
|
||||
```
|
||||
|
||||
Every few mintutes watchtower will pull the latest *centurylink/wetty-cli* image and compare it to the one that was used to run the "wetty" container. If it sees that the image has changed it will stop/remove the "wetty" container and then restart it using the new image and the same `docker run` options that were used to start the container initially (in this case, that would include the `-p 8080:3000` port mapping).
|
||||
|
||||
## Usage
|
||||
|
||||
Watchtower is itself packaged as a Docker container so installation is a simple as pulling the `centurylink/watchtower` image.
|
||||
Watchtower is itself packaged as a Docker container so installation is as simple as pulling the `v2tec/watchtower` image.
|
||||
|
||||
Since the watchtower code needs to interact with the Docker API in order to monitor the running containers, you need to mount */var/run/docker.sock* into the container with the -v flag when you run it.
|
||||
|
||||
|
@ -36,7 +34,7 @@ Run the `watchtower` container with the following command:
|
|||
docker run -d \
|
||||
--name watchtower \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
centurylink/watchtower
|
||||
v2tec/watchtower
|
||||
```
|
||||
|
||||
If pulling images from private Docker registries, supply registry authentication credentials with the environment variables `REPO_USER` and `REPO_PASS`
|
||||
|
@ -58,7 +56,7 @@ By default, watchtower will monitor all containers running within the Docker dae
|
|||
docker run -d \
|
||||
--name watchtower \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
centurylink/watchtower nginx redis
|
||||
v2tec/watchtower nginx redis
|
||||
```
|
||||
|
||||
In the example above, watchtower will only monitor the containers named "nginx" and "redis" for updates -- all of the other running containers will be ignored.
|
||||
|
@ -70,11 +68,12 @@ When no arguments are specified, watchtower will monitor all running containers.
|
|||
Any of the options described below can be passed to the watchtower process by setting them after the image name in the `docker run` string:
|
||||
|
||||
```
|
||||
docker run --rm centurylink/watchtower --help
|
||||
docker run --rm v2tec/watchtower --help
|
||||
```
|
||||
|
||||
* `--host, -h` Docker daemon socket to connect to. Defaults to "unix:///var/run/docker.sock" but can be pointed at a remote Docker host by specifying a TCP endpoint as "tcp://hostname:port". The host value can also be provided by setting the `DOCKER_HOST` environment variable.
|
||||
* `--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.
|
||||
* `--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.
|
||||
|
@ -112,7 +111,7 @@ By default, watchtower is set-up to monitor the local Docker daemon (the same da
|
|||
```
|
||||
docker run -d \
|
||||
--name watchtower \
|
||||
centurylink/watchtower --host "tcp://10.0.1.2:2375"
|
||||
v2tec/watchtower --host "tcp://10.0.1.2:2375"
|
||||
```
|
||||
|
||||
or
|
||||
|
@ -121,7 +120,7 @@ or
|
|||
docker run -d \
|
||||
--name watchtower \
|
||||
-e DOCKER_HOST="tcp://10.0.1.2:2375" \
|
||||
centurylink/watchtower
|
||||
v2tec/watchtower
|
||||
```
|
||||
|
||||
Note in both of the examples above that it is unnecessary to mount the */var/run/docker.sock* into the watchtower container.
|
||||
|
@ -139,9 +138,9 @@ docker run -d \
|
|||
--name watchtower \
|
||||
-e DOCKER_HOST=$DOCKER_HOST \
|
||||
-v $DOCKER_CERT_PATH:/etc/ssl/docker \
|
||||
centurylink/watchtower --tlsverify
|
||||
v2tec/watchtower --tlsverify
|
||||
```
|
||||
|
||||
## Updating Watchtower
|
||||
|
||||
If watchtower is monitoring the same Docker daemon under which the watchtower container itself is running (i.e. if you volume-mounted */var/run/docker.sock* into the watchtower container) then it has the ability to update itself. If a new version of the *centurylink/watchtower* image is pushed to the Docker Hub, your watchtower will pull down the new image and restart itself automatically.
|
||||
If watchtower is monitoring the same Docker daemon under which the watchtower container itself is running (i.e. if you volume-mounted */var/run/docker.sock* into the watchtower container) then it has the ability to update itself. If a new version of the *v2tec/watchtower* image is pushed to the Docker Hub, your watchtower will pull down the new image and restart itself automatically.
|
||||
|
|
|
@ -3,7 +3,7 @@ package actions
|
|||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/CenturyLinkLabs/watchtower/container"
|
||||
"github.com/v2tec/watchtower/container"
|
||||
)
|
||||
|
||||
func watchtowerContainersFilter(c container.Container) bool { return c.IsWatchtower() }
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/CenturyLinkLabs/watchtower/container"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/v2tec/watchtower/container"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -34,7 +34,7 @@ func containerFilter(names []string) container.Filter {
|
|||
// used to start those containers have been updated. If a change is detected in
|
||||
// any of the images, the associated containers are stopped and restarted with
|
||||
// the new image.
|
||||
func Update(client container.Client, names []string, cleanup bool) error {
|
||||
func Update(client container.Client, names []string, cleanup bool, noRestart bool) error {
|
||||
log.Info("Checking containers for updated images")
|
||||
|
||||
containers, err := client.ListContainers(containerFilter(names))
|
||||
|
@ -88,8 +88,10 @@ func Update(client container.Client, names []string, cleanup bool) error {
|
|||
}
|
||||
}
|
||||
|
||||
if err := client.StartContainer(container); err != nil {
|
||||
log.Error(err)
|
||||
if !noRestart {
|
||||
if err := client.StartContainer(container); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
if cleanup {
|
||||
|
|
21
circle.yml
21
circle.yml
|
@ -1,30 +1,13 @@
|
|||
machine:
|
||||
services:
|
||||
- docker
|
||||
environment:
|
||||
IMAGE_NAME: centurylink/watchtower
|
||||
|
||||
dependencies:
|
||||
override:
|
||||
- docker pull centurylink/golang-builder:latest
|
||||
- go get -u github.com/Masterminds/glide
|
||||
|
||||
test:
|
||||
override:
|
||||
- glide install
|
||||
- docker run -v $(pwd):/src centurylink/golang-builder:latest --test
|
||||
|
||||
deployment:
|
||||
hub:
|
||||
branch: master
|
||||
commands:
|
||||
- docker run -v $(pwd):/src centurylink/golang-builder:latest
|
||||
- docker build -t $IMAGE_NAME:latest .
|
||||
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
|
||||
- docker push $IMAGE_NAME:latest
|
||||
hub_mirror:
|
||||
branch: [master, auth]
|
||||
owner: rosscado
|
||||
commands:
|
||||
- docker run -v $(pwd):/src centurylink/golang-builder:latest
|
||||
- docker build -t rosscado/watchtower:latest .
|
||||
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
|
||||
- docker push rosscado/watchtower:latest
|
||||
|
|
|
@ -165,10 +165,9 @@ func (client dockerClient) StartContainer(c Container) error {
|
|||
}
|
||||
|
||||
func (client dockerClient) RenameContainer(c Container, newName string) error {
|
||||
bg := context.Background()
|
||||
log.Debugf("Renaming container %s (%s) to %s", c.Name(), c.ID(), newName)
|
||||
//return client.api.ContainerRename(c.ID(), newName)
|
||||
// no op
|
||||
return nil
|
||||
return client.api.ContainerRename(bg, c.ID(), newName)
|
||||
}
|
||||
|
||||
func (client dockerClient) IsContainerStale(c Container) (bool, error) {
|
||||
|
|
|
@ -3,8 +3,8 @@ package mockclient
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/CenturyLinkLabs/watchtower/container"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/v2tec/watchtower/container"
|
||||
)
|
||||
|
||||
type MockClient struct {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/CenturyLinkLabs/watchtower/container"
|
||||
"github.com/v2tec/watchtower/container"
|
||||
)
|
||||
|
||||
func TestMockInterface(t *testing.T) {
|
||||
|
|
|
@ -2,6 +2,9 @@ package container
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/reference"
|
||||
|
@ -9,8 +12,6 @@ import (
|
|||
"github.com/docker/docker/cliconfig"
|
||||
"github.com/docker/docker/cliconfig/configfile"
|
||||
"github.com/docker/docker/cliconfig/credentials"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/**
|
||||
|
@ -80,14 +81,13 @@ func ParseServerAddress(ref string) (string, error) {
|
|||
}
|
||||
parts := strings.Split(repository, "/")
|
||||
return parts[0], nil
|
||||
|
||||
}
|
||||
|
||||
// CredentialsStore returns a new credentials store based
|
||||
// on the settings provided in the configuration file.
|
||||
func CredentialsStore(configFile configfile.ConfigFile) credentials.Store {
|
||||
if configFile.CredentialsStore != "" {
|
||||
return credentials.NewNativeStore(&configFile)
|
||||
return credentials.NewNativeStore(&configFile, configFile.CredentialsStore)
|
||||
}
|
||||
return credentials.NewFileStore(&configFile)
|
||||
}
|
||||
|
|
186
glide.lock
generated
Normal file
186
glide.lock
generated
Normal file
|
@ -0,0 +1,186 @@
|
|||
hash: 9ddd729b207d71ce16ae9a0282ac87a046b9161ac4f15b108e86a03367172516
|
||||
updated: 2017-01-24T20:45:43.1914053+01:00
|
||||
imports:
|
||||
- name: github.com/Azure/go-ansiterm
|
||||
version: 388960b655244e76e24c75f48631564eaefade62
|
||||
subpackages:
|
||||
- winterm
|
||||
- name: github.com/davecgh/go-spew
|
||||
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||
subpackages:
|
||||
- spew
|
||||
- name: github.com/docker/distribution
|
||||
version: 28602af35aceda2f8d571bad7ca37a54cf0250bc
|
||||
subpackages:
|
||||
- context
|
||||
- digest
|
||||
- reference
|
||||
- registry/api/errcode
|
||||
- registry/api/v2
|
||||
- registry/client
|
||||
- registry/client/auth
|
||||
- registry/client/auth/challenge
|
||||
- registry/client/transport
|
||||
- registry/storage/cache
|
||||
- registry/storage/cache/memory
|
||||
- uuid
|
||||
- name: github.com/docker/docker
|
||||
version: 49bf474f9ed7ce7143a59d1964ff7b7fd9b52178
|
||||
subpackages:
|
||||
- api
|
||||
- api/server/httputils
|
||||
- api/types
|
||||
- api/types/blkiodev
|
||||
- api/types/container
|
||||
- api/types/events
|
||||
- api/types/filters
|
||||
- api/types/mount
|
||||
- api/types/network
|
||||
- api/types/reference
|
||||
- api/types/registry
|
||||
- api/types/strslice
|
||||
- api/types/swarm
|
||||
- api/types/time
|
||||
- api/types/versions
|
||||
- api/types/volume
|
||||
- cli/command
|
||||
- cli/flags
|
||||
- cliconfig
|
||||
- cliconfig/configfile
|
||||
- cliconfig/credentials
|
||||
- client
|
||||
- daemon/graphdriver
|
||||
- dockerversion
|
||||
- image
|
||||
- image/v1
|
||||
- layer
|
||||
- oci
|
||||
- opts
|
||||
- pkg/archive
|
||||
- pkg/chrootarchive
|
||||
- pkg/fileutils
|
||||
- pkg/homedir
|
||||
- pkg/httputils
|
||||
- pkg/idtools
|
||||
- pkg/ioutils
|
||||
- pkg/jsonlog
|
||||
- pkg/jsonmessage
|
||||
- pkg/longpath
|
||||
- pkg/mount
|
||||
- pkg/parsers/kernel
|
||||
- pkg/plugingetter
|
||||
- pkg/plugins
|
||||
- pkg/plugins/transport
|
||||
- pkg/pools
|
||||
- pkg/promise
|
||||
- pkg/random
|
||||
- pkg/reexec
|
||||
- pkg/stringid
|
||||
- pkg/system
|
||||
- pkg/tarsum
|
||||
- pkg/term
|
||||
- pkg/term/windows
|
||||
- pkg/tlsconfig
|
||||
- pkg/useragent
|
||||
- plugin/v2
|
||||
- reference
|
||||
- registry
|
||||
- name: github.com/docker/docker-credential-helpers
|
||||
version: f72c04f1d8e71959a6d103f808c50ccbad79b9fd
|
||||
subpackages:
|
||||
- client
|
||||
- credentials
|
||||
- name: github.com/docker/go-connections
|
||||
version: 4ccf312bf1d35e5dbda654e57a9be4c3f3cd0366
|
||||
subpackages:
|
||||
- nat
|
||||
- sockets
|
||||
- tlsconfig
|
||||
- name: github.com/docker/go-units
|
||||
version: 8a7beacffa3009a9ac66bad506b18ffdd110cf97
|
||||
- name: github.com/docker/libtrust
|
||||
version: 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
- name: github.com/golang/protobuf
|
||||
version: 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a
|
||||
subpackages:
|
||||
- proto
|
||||
- name: github.com/gorilla/context
|
||||
version: 1ea25387ff6f684839d82767c1733ff4d4d15d0a
|
||||
- name: github.com/gorilla/mux
|
||||
version: 0eeaf8392f5b04950925b8a69fe70f110fa7cbfc
|
||||
- name: github.com/inconshreveable/mousetrap
|
||||
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
|
||||
- name: github.com/mattn/go-shellwords
|
||||
version: f4e566c536cf69158e808ec28ef4182a37fdc981
|
||||
- name: github.com/Microsoft/go-winio
|
||||
version: 24a3e3d3fc7451805e09d11e11e95d9a0a4f205e
|
||||
- name: github.com/opencontainers/runc
|
||||
version: 2f7393a47307a16f8cee44a37b262e8b81021e3e
|
||||
repo: https://github.com/docker/runc.git
|
||||
subpackages:
|
||||
- libcontainer/configs
|
||||
- libcontainer/devices
|
||||
- libcontainer/system
|
||||
- libcontainer/user
|
||||
- name: github.com/opencontainers/runtime-spec
|
||||
version: 1c7c27d043c2a5e513a44084d2b10d77d1402b8c
|
||||
subpackages:
|
||||
- specs-go
|
||||
- name: github.com/pkg/errors
|
||||
version: 839d9e913e063e28dfd0e6c7b7512793e0a48be9
|
||||
- name: github.com/pmezard/go-difflib
|
||||
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||
subpackages:
|
||||
- difflib
|
||||
- name: github.com/robfig/cron
|
||||
version: 9585fd555638e77bba25f25db5c44b41f264aeb7
|
||||
- name: github.com/Sirupsen/logrus
|
||||
version: d26492970760ca5d33129d2d799e34be5c4782eb
|
||||
- name: github.com/spf13/cobra
|
||||
version: a3c09249f1a24a9d951f2738fb9b9256b8b42fa5
|
||||
repo: https://github.com/dnephin/cobra.git
|
||||
- name: github.com/spf13/pflag
|
||||
version: dabebe21bf790f782ea4c7bbd2efc430de182afd
|
||||
- name: github.com/stretchr/objx
|
||||
version: cbeaeb16a013161a98496fad62933b1d21786672
|
||||
- name: github.com/stretchr/testify
|
||||
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
|
||||
subpackages:
|
||||
- assert
|
||||
- mock
|
||||
- name: github.com/urfave/cli
|
||||
version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6
|
||||
- name: github.com/vbatts/tar-split
|
||||
version: d3f1b54304d656376e58f9406a9cb4775799a357
|
||||
subpackages:
|
||||
- archive/tar
|
||||
- tar/asm
|
||||
- tar/storage
|
||||
- name: golang.org/x/net
|
||||
version: 2beffdc2e92c8a3027590f898fe88f69af48a3f8
|
||||
repo: https://github.com/tonistiigi/net.git
|
||||
subpackages:
|
||||
- context
|
||||
- context/ctxhttp
|
||||
- http2
|
||||
- http2/hpack
|
||||
- internal/timeseries
|
||||
- proxy
|
||||
- trace
|
||||
- name: golang.org/x/sys
|
||||
version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
|
||||
subpackages:
|
||||
- unix
|
||||
- windows
|
||||
- name: google.golang.org/grpc
|
||||
version: b1a2821ca5a4fd6b6e48ddfbb7d6d7584d839d21
|
||||
subpackages:
|
||||
- codes
|
||||
- credentials
|
||||
- grpclog
|
||||
- internal
|
||||
- metadata
|
||||
- naming
|
||||
- peer
|
||||
- transport
|
||||
testImports: []
|
28
glide.yaml
Normal file
28
glide.yaml
Normal file
|
@ -0,0 +1,28 @@
|
|||
package: github.com/stffabi/watchtower
|
||||
import:
|
||||
- package: github.com/Sirupsen/logrus
|
||||
version: ~0.11.x
|
||||
- package: github.com/docker/docker
|
||||
version: ~1.13.x
|
||||
subpackages:
|
||||
- api/types
|
||||
- api/types/container
|
||||
- api/types/network
|
||||
- api/types/reference
|
||||
- cli/command
|
||||
- cliconfig
|
||||
- cliconfig/configfile
|
||||
- cliconfig/credentials
|
||||
- client
|
||||
- package: github.com/stretchr/testify
|
||||
version: ~1.1.4
|
||||
subpackages:
|
||||
- mock
|
||||
- package: github.com/urfave/cli
|
||||
version: ~1.19.1
|
||||
- package: golang.org/x/net
|
||||
repo: https://github.com/tonistiigi/net.git
|
||||
subpackages:
|
||||
- context
|
||||
- package: github.com/robfig/cron
|
||||
version: 9585fd555638e77bba25f25db5c44b41f264aeb7
|
111
main.go
111
main.go
|
@ -1,24 +1,26 @@
|
|||
package main // import "github.com/CenturyLinkLabs/watchtower"
|
||||
package main // import "github.com/v2tec/watchtower"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/CenturyLinkLabs/watchtower/actions"
|
||||
"github.com/CenturyLinkLabs/watchtower/container"
|
||||
"strconv"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/robfig/cron"
|
||||
"github.com/urfave/cli"
|
||||
"github.com/v2tec/watchtower/actions"
|
||||
"github.com/v2tec/watchtower/container"
|
||||
)
|
||||
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
client container.Client
|
||||
pollInterval time.Duration
|
||||
scheduleSpec string
|
||||
cleanup bool
|
||||
noRestart bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -39,17 +41,30 @@ func main() {
|
|||
EnvVar: "DOCKER_HOST",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "interval, i",
|
||||
Usage: "poll interval (in seconds)",
|
||||
Value: 300,
|
||||
Name: "interval, i",
|
||||
Usage: "poll interval (in seconds)",
|
||||
Value: 300,
|
||||
EnvVar: "WATCHTOWER_POLL_INTERVAL",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "schedule, s",
|
||||
Usage: "the cron expression which defines when to update",
|
||||
EnvVar: "WATCHTOWER_SCHEDULE",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "no-pull",
|
||||
Usage: "do not pull new images",
|
||||
Name: "no-pull",
|
||||
Usage: "do not pull new images",
|
||||
EnvVar: "WATCHTOWER_NO_PULL",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "cleanup",
|
||||
Usage: "remove old images after updating",
|
||||
Name: "no-restart",
|
||||
Usage: "do not restart containers",
|
||||
EnvVar: "WATCHTOWER_NO_RESTART",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "cleanup",
|
||||
Usage: "remove old images after updating",
|
||||
EnvVar: "WATCHTOWER_CLEANUP",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "tlsverify",
|
||||
|
@ -77,8 +92,19 @@ func before(c *cli.Context) error {
|
|||
log.SetLevel(log.DebugLevel)
|
||||
}
|
||||
|
||||
pollInterval = time.Duration(c.Int("interval")) * time.Second
|
||||
pollingSet := c.IsSet("interval")
|
||||
cronSet := c.IsSet("schedule")
|
||||
|
||||
if pollingSet && cronSet {
|
||||
log.Fatal("Only schedule or interval can be defined, not both.")
|
||||
} else if cronSet {
|
||||
scheduleSpec = c.String("schedule")
|
||||
} else {
|
||||
scheduleSpec = "@every " + strconv.Itoa(c.Int("interval")) + "s"
|
||||
}
|
||||
|
||||
cleanup = c.GlobalBool("cleanup")
|
||||
noRestart = c.GlobalBool("no-restart")
|
||||
|
||||
// configure environment vars for client
|
||||
err := envConfig(c)
|
||||
|
@ -87,40 +113,57 @@ func before(c *cli.Context) error {
|
|||
}
|
||||
|
||||
client = container.NewClient(!c.GlobalBool("no-pull"))
|
||||
|
||||
handleSignals()
|
||||
return nil
|
||||
}
|
||||
|
||||
func start(c *cli.Context) {
|
||||
func start(c *cli.Context) error {
|
||||
names := c.Args()
|
||||
|
||||
if err := actions.CheckPrereqs(client, cleanup); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for {
|
||||
wg.Add(1)
|
||||
if err := actions.Update(client, names, cleanup); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
wg.Done()
|
||||
tryLockSem := make(chan bool, 1)
|
||||
tryLockSem <- true
|
||||
|
||||
time.Sleep(pollInterval)
|
||||
cron := cron.New()
|
||||
err := cron.AddFunc(
|
||||
scheduleSpec,
|
||||
func() {
|
||||
select {
|
||||
case v := <-tryLockSem:
|
||||
defer func() { tryLockSem <- v }()
|
||||
if err := actions.Update(client, names, cleanup, noRestart); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
default:
|
||||
log.Debug("Skipped another update already running.")
|
||||
}
|
||||
|
||||
nextRuns := cron.Entries()
|
||||
if len(nextRuns) > 0 {
|
||||
log.Debug("Scheduled next run: " + nextRuns[0].Next.String())
|
||||
}
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func handleSignals() {
|
||||
log.Info("First run: " + cron.Entries()[0].Schedule.Next(time.Now()).String())
|
||||
cron.Start()
|
||||
|
||||
// Graceful shut-down on SIGINT/SIGTERM
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
signal.Notify(c, syscall.SIGTERM)
|
||||
interrupt := make(chan os.Signal, 1)
|
||||
signal.Notify(interrupt, os.Interrupt)
|
||||
signal.Notify(interrupt, syscall.SIGTERM)
|
||||
|
||||
go func() {
|
||||
<-c
|
||||
wg.Wait()
|
||||
os.Exit(1)
|
||||
}()
|
||||
<-interrupt
|
||||
cron.Stop()
|
||||
log.Info("Waiting for running update to be finished...")
|
||||
<-tryLockSem
|
||||
os.Exit(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func setEnvOptStr(env string, opt string) error {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue