Keeping my Homelab Docker containers up-to-date with Renovate
Table of Contents
Please consider leaving a small gesture of your appreciation.
Introduction #
As part of the ongoing project to make my Homelab more easily maintainable, I stumbled across Renovate by Mend.IO. Renovate is intended to keep dependencies up-to-date within a software development environment, however I’ve found it can be quite easily turned to keeping my Docker Containers up to date.
My workflow #
As I’ve mentioned
on a previous post, I run a
Docker Swarm across a number of virtual machines.
Rather than load the
Docker Compose files manually, I run
Portainer as a GUI for easy access.
This gives me the option to run
GitOps for automated deployment of these Compose files.
I have a private
Github repository with a separate folder for each stack I run, which contains the docker-compose.yml
file along with any associated environment variables needed.
Through the GitOps magic, whenever I push a new commit to this repository, Portainer will pull down the updated configuration within a matter of minutes and deploy this on the Swarm.
’latest’ is bad! #
The problem I’ve been running in to is a product of my own lack of understanding and general laziness.
When setting up most of these Compose files, I’ve either copy & pasted configuration from someone elses work, or roughly created my own.
In this laziness, I ended up with a lot of Compose files referencing either a vastly outdated or the :latest
version of an image, with no idea how much trouble this could cause me down the line.
A problem with Docker Swarm is that you have little to no control over when a new image will be pulled. If one of my nodes loses connectivity or otherwise drops out of the Swarm, then the tasks will be assigned elsewhere, which may mean an updated image is pulled from whichever repository you happen to be using. If you’re particularly unlucky, and this new version contains some breaking changes, then your application could well cease working!
The fix for this issue is locking the image version to a specific one, such as image: nginx:1.27.1
, however this introduces a new issue - what happens when a new version is tagged?
With a fixed image version, any new releases will be ignored, and any gains in stability will quickly be overcome by
technical debt as you fall behind the update curve.
Renovate enters the chat #
By adding Renovate to my Github repository (their tutorial for doing this is very easy to follow), the service now scans my repository for any Docker Compose files, and pulls all the images referenced. These are then checked against the respective Docker repository for any newer versions, and a Pull Request will be automatically generated any time an update is found. You can then review the PR, and if it’s only a minor update a simple merge will trigger Portainer to pull the new image and deploy automatically. Any more complicated updates can be handled manually, and the PR will be automatically closed again once you’ve finished.
I’ve not done much exploring of the configuration yet, but here’s what I’m using so far:
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"docker-compose": {
"fileMatch": [
"(^|/)(?:docker-)?compose[^/]*\\.ya?ml$",
"(.*)yaml$"
]
}
}
This will treat any *.yaml
file within the repository as a docker-compose
file.
I don’t always follow the docker-compose.yaml
suggested format, so this makes sure all of my compose files are scanned.
What next? #
Depending on how many Stacks you run, the quantity of updates could be pretty high. I’ve only had this service running for a matter of weeks, but at some points I’ve had multiple emails per day from Github warning of new Pull Requests to my repository. The next thing I’m going to investigate is modifying the above configuration to automatically approve any PRs that only contain ‘minor’ updates through their Automerge functionality, but I want to be a little more certain about the concept before committing to automatic upgrades again!