Keep services in a Docker stack always up-to-date automatically to latest images.
1.7K
A NodeJs based docker image to keep services in a Docker stack always up-to-date to their latest images.
I use Docker stacks in my environment. It was becoming pretty mundane to keep checking for latest images against my services on a periodic basis. The service in my stack also had dependencies within each other, and juggling each time to decide which service comes before which was a pain during the manual update. I usually tore down my stack itself, updated the latest image tags against each service and then relaunched my stack fresh once again. Few services had to be on some specific version of an image, few could always go upto latest, and rest had a need to stick to specific tag prefixes. Not to mention, I also had to prune up any unused containers, dangling images - manually every time I went through this update process.
I came across Watchtower and did find it pretty impressive. However, it is feature-rich and has some advanced features into it that I found a little complicated to research into. Watchtower may've solved what I was after, but I decided to instead write a simple NodeJs script specific to my needs.
Here is how my script - Somnus (In Roman mythology, Somnus ("sleep") is the personification of sleep) works like this.
Somnus uses Dockerode under the covers. Dockerode is an excellent library that simplifies working against the Docker Engine API.
Invoke somnus as a standalone container like this-
$ docker run \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
-v ./logs:/app/logs:rw \
-v ./somnus.yml:/app/somnus.yml:ro \
-w /app \
somnus:latest --config somnus.yml
somnus.yml contains default settings to use Docker hub as well as socketPath to connect to your running Docker engine can be specified there. Please use the sample somnus.yml available in the project repo.
Somnus currently supports the below parameters
Options:
-v, --version output the current version
-c, --config <config.yml> path to somnus.yml config
-d, --dry-run if specified, just do a dry run but do not actually update anything
-h, --help output usage information
In addition, the logs folder contains the log of the entire operation done by Somnus. Any older log files over 5 days are deleted automatically. Logs within 5 days are zipped to save space. The latest log is always available at logs/somnus.log
All running Docker services are listed. All services across all Docker stacks are listed.
Services are parsed using Docker labels. Usually the defaults are sufficient, but if these are specified on the service as label, then that value will be used instead.
Most likely, you'll want to use somnus.defaults.enable and somnus.defaults.order labels compared to the rest of them.
All defaults except enable, order are specified in somnus.yml.
| Label | Default Value | Description |
|---|---|---|
somnus.defaults.enable | true | Set this label on a service to enable or disable this for Somnus to target for autoupdate. |
somnus.defaults.order | 0 | Determines the order in which services within a Docker stack should be updated. Somnus will update any services with same order in parallel. Lower numbered order is updated first then next higher order in sequence. Useful to explicitly control a bunch of related services within a stack to get updated before others in sequence. Somnus will wait until the updated service has achieved completed state which means the updated service is fully up and running.Note: All Docker Stacks are updated in parallel. order matters only within that stack. |
somnus.defaults.latest.tag | latest | Specify which tag represents the latest image for the service.This value can be partial tag such as alpine, buster used in some popular images, or it could be a few characters such as 5 for example to stick to 5x series of mysql.Behind the scenes the tags are matched for similarity using a Levenshtein distance using leven and then the longest match is used to determine the latest image tag to update to. Tip: Use --dry-run when running somuns to check if the latest tag is what you expect it to be. |
somnus.defaults.registry | hub.docker.com | Somnus uses the official Docker Hub for updates by default. |
somnus.defaults.version | v2 | Used to create the standard Docker Hub url to fetch latest tags for an image |
somnus.defaults.namespace | library | Default namespace for official Docker images. For images that use a custom namespace e.g. containous/whoamithe namespace is automatically adjusted to fetch the correct tags from that custom namespace. |
somnus.defaults.architecture | amd64 | Used to determine to correct image tag suitable for architecture on which current Docker Engine is running. |
somnus.defaults.os | linux | Used to determine the suitable OS version for the image tag. |
Each service is checked to see if it has a newer image tag available.
If a newer image tag is available then the service is updated to use that tag. Somnus waits until the service reports completed as it's status after updating. Somnus then proceeds to the next service to update based on order.
As a final step, any stopped containers, unused images are removed.
Once you verify that the above docker run command works for your stack, then declare somnus like any other service in your Docker stack and you're good to go.
Note: You only need to define somnus once in one of your Docker stacks, perhaps a master stack. Somnus will keep updating all services across all stacks currently deployed in your Docker engine.
# My example service that I want to always keep up-to-date using Somnus
mongo:
image: mongo:4.2.1-bionic
labels:
# Somnus autoupdate tags. Latest 'bionic' tags for mongo should be kept up-to-date.
- "somnus.defaults.latest.tag=bionic"
- "somnus.defaults.enable=true"
command: ["mongod", "--config", "/etc/mongod.conf"]
ports:
- ...
volumes:
- ...
environment:
- ...
# Declare Somnus like any other service in your stack. Since just one global service is sufficient
# you can specify the service placement to be `global` and restricted to a `manager` node.
somnus:
image: visitsb/somnus:1.0
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /somnus/somnus.yml:/app/somnus.yml:ro
- /somnus/logs:/app/logs:rw
deploy:
mode: global
placement:
constraints:
- node.role == manager
...
By default, somnus.yml has a schedule to auto update once daily. You can change the schedule using a different schedule.
Restart somnus service to pick up the new schedule and somnus will happily keep all of your services up-to-date.
Please use Github to post your issues, suggestions. PRs are welcome too. Let Somnus save you some quality time in your Docker infrastructure.
Content type
Image
Digest
Size
358.3 MB
Last updated
over 5 years ago
docker pull visitsb/somnus