edge-device-image-updater
This repository serves as an example of how to use diun with Docker Swarm to automatically detect image updates on edge devices, apply them, and have rollback functionality in the event of a failed update.
This works as follows:
- A custom diun image was created to have the
dockerCLI installed (Dockerfile). This allows scripts run by the diun container to interact with the Docker daemon on the host machine. - A simple script was created to list all containers in the Docker Swarm and update them.
- Whatever service(s) you're looking to run on your edge device, add them to a
docker-stackfile that also hasdiunconfigured so it can monitor all the images in the stack. In this instance, I simply bundled my radarr-mock image with the diun image. - Deploy the stack using
docker stack deploy -c docker-stack.yml test-stack
Prerequisites
System Initialization
In order to use Docker Swarm on your device, you must first initialize it via docker swarm init.
Docker Credentials
In order to allow the diun container to monitor images in private repositories, you must update the following line in the docker-stack.yml:
---
services:
diun:
...
volumes:
...
- "/path/to/docker/config.json:/root/.docker/config.json:ro"
Deploying
To deploy this stack, simply run docker stack deploy -c docker-stack.yml test-stack.
Detailed Explanation
What is Diun?
Docker Image Update Notifier (diun) is a CLI application to receive notifications when a Docker image is updated on a Docker registry. It allows us to execute a script whenever it detects a new image version, which we can use to automatically update our services.
What's Happening in the Docker Compose file?
In the docker-stack.yml, I have listed two services: diun and radarr-mock. The former is for monitoring and notifying on new image versions, and the latter is an example of an application image that we want to keep updated.
Diun Service
There's a few points to note in the diun service configuration:
Volumes
We mount the following volumes into the diun container:
| Volume | Description |
|---|---|
/var/run/docker.sock:/var/run/docker.sock |
This is how the diun container interacts with the Docker daemon on the host machine. It allows the diun container to list all the images, containers, etc. |
./swarm-update.sh:/swarm-update.sh |
Mount the script that will be executed on image updates. |
/path/to/docker/config.json:/root/.docker/config.json:ro |
Mount the Docker configuration file so that diun can monitor images in private repositories. |
Environment Variables
The diun service is configured using environment variables. The most important ones are:
| Variable | Description |
|---|---|
DIUN_WATCH_SCHEDULE='*/1 * * * *' |
This variable is used to set the schedule for checking for new image versions. In this case, it is set to check once every minute. |
DIUN_PROVIDERS_SWARM=true |
This variable instructs diun to use Docker Swarm to detect running services to detect their images and to monitor them (see Diun Providers) |
DIUN_NOTIF_SCRIPT_CMD=sh |
Tell diun that it needs to execute a sh script when a new image is detected. This is considered a script notification |
DIUN_NOTIF_SCRIPT_ARGS=/swarm-update.sh |
Indicate to diun that we want to run the script /swarm-update.sh when a new image is detected (see this discussion to understand why we're calling it like this) |
Radarr-Mock Service
In the Radarr Mock service, there's only a couple of points of interest that may differ from your standard Docker Compose service definition.
Configure Rollbacks for Failed Updates
Whenever an update fails, we want to ensure continued service. To achieve this, we use Docker Swarm's rollback capabilities on the service. It is configured as follows:
radarr-mock:
deploy:
update_config:
order: start-first
failure_action: rollback
delay: 10s
parallelism: 1
This ensures that if ever an update to this service fails, Docker Swarm will rollback to the previous version. Additionally, order: start-first ensures the new version is healthy before stopping the old one.
Configure the Restart Policy to Prevent Boot Loops
Additionally, there's occasionally situations where a service will fail to start, causing Docker Swarm to restart the service, which in turn fails again. To prevent this, we configure the service to only try a max of 3 times to start the service before giving up:
radarr-mock:
deploy:
restart_policy:
condition: on-failure
max_attempts: 3
delay: 5s
Specify the Health Check to Ensure Service is Healthy
We also want to ensure that Docker Swarm knows that our service is healthy. This is achieved by using the healthcheck directive in the service definition:
radarr-mock:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7878"]
interval: 10s
timeout: 3s
retries: 2
start_period: 10s
Label the Service for Diun Monitoring
And finally, to ensure that diun monitors this service, we add the following label to the service definition:
radarr-mock:
deploy:
labels:
- "diun.enable=true"