c’t 07/2026
Wat is er waar van IT-mythes?
Cover van
Docker container updaten automatisch Watchtower alternatief

Docker-containers updaten: drie opties voor automatisch updaten

Er zijn verschillende oplossingen om verouderde Docker-images te vervangen door nieuwere. We gaan in op drie opties, van eenvoudige update-automatisering tot GitOps-pipeline.

Van image naar nieuwe container

Het updaten van Docker-containers verschilt in veel opzichten van updates die worden geïnstalleerd met behulp van de pakketbeheerder van een besturingssysteem. Het commando apt upgrade in Ubuntu vervangt individuele bestanden en kan systeemdiensten herstarten. Een container is echter een instantie van een onveranderlijke image.

Het wordt niet aanbevolen om de interne structuur van een image bij te werken. Stop in plaats daarvan de oude container, bouw een nieuwe of haal die uit een registry en gooi de oude weg. Persistente gegevens worden buiten de container bewaard en zijn na het herstarten weer beschikbaar. Dat is de enige reden waarom het weggooiprincipe werkt.

Docker heeft zelf geen tools die het verwisselen van images vergemakkelijken of automatiseren. De concurrerende containerengine Podman heeft het label io.containers.autoupdate=registry, dat updates automatiseert met een systemd-timer.

Watchtower

In de Docker-wereld heeft het communityproject Watchtower die leemte lange tijd opgevuld. Het is zelf een container die de Docker-socket mount en gebruikt om de configuratie van de draaiende containers te lezen.

Op gezette tijden vraagt het de registry om de digest van de gebruikte tag, bijvoorbeeld nginx.1.27. Als de digest anders is, oftewel als er een nieuwer image beschikbaar is, haalt Watchtower de nieuwe image op (vergelijkbaar met docker pull in de CLI) en maakt er een container van (vergelijkbaar met docker run in de CLI).

Watchtower gebruikt een verouderde versie van Dockers Go-SDK, die versie 1.25 vereist voor API-verzoeken. Docker Engine 29 heeft echter de minimale versie van de API verhoogd naar 1.44 en wijst verzoeken van oudere versies af.

Sinds Docker Engine 29 werkt Watchtower niet meer zonder een workaround. De twee beheerders hebben de GitHub-repository van het project (containrrr/watchtower) sindsdien gearchiveerd en verklaard dat ze geen tijd en motivatie hebben om Watchtower te blijven onderhouden.

Sindsdien zijn er verschillende forks opgestaan om het stokje over te nemen. Een daarvan is te vinden in de nickfedor/watchtower-repository. Die fork wordt goed onderhouden, werkt de afhankelijkheden wekelijks bij en heeft regelmatig releases met changelogs.
Bijzonder praktisch: om te migreren is het voldoende om de containrrr/watchtower-image te vervangen door nickfedor/watchtower. Bestaande labels en intervallen blijven werken.

Maar iedereen die containers tot nu toe automatisch heeft bijgewerkt met Watchtower, kan het einde van het oorspronkelijke project ook aangrijpen om rond te kijken naar alternatieven. De fork kan ooit hetzelfde lot ondergaan als het oorspronkelijke project. Watchtower vervangt op betrouwbare wijze containerimages door nieuwere, maar daarbij geef je als beheerder wel de controle deels uit handen.

Dat geldt slechts in beperkte mate als je de versies van je images uit voorzorg vastpint, bijvoorbeeld door nginx.1.27 op te geven in plaats van nginx.latest in een Compose-bestand. Omdat Watchtower de Compose-bestanden echter niet herkent of wijzigt, is het noodzakelijk om ze regelmatig zelf te bewerken om containers bij te werken naar nieuwere versies.

We beschrijven hier twee tools voor het bijwerken van containerimages die meer controle bieden. WUD, oftewel ‘What’s up Docker?’, is een auto-updater voor containers die ook Compose-bestanden herkent en een minimalistische webinterface biedt.

Doco-CD is een tool die de GitOps-aanpak overbrengt naar Docker Compose. Bij de grote broer van Docker, de container-orchestrator Kubernetes, hebben tools als Flux en Argo CD het GitOps-principe tot een succes gemaakt. Een Git-repository is daarbij de ‘single source of truth’ (SSOT) en bewaart zowel app- als infrastructuurconfiguraties. Daardoor zijn wijzigingen traceerbaar en eenvoudig ongedaan te maken. In combinatie met tools als Renovate kan een updatepipeline dan snel worden gebouwd.

What’s up Docker?

De functionaliteit van WUD is goed te begrijpen als je het Docker Compose-bestand bekijkt, dat we ook in een GitHub-repository voor dit artikel beschikbaar stellen (zie de link bij dit artikel).

services:
wud:
image: getwud/wud:8.2.2
container_name: wud
ports:
- "3000:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./demo/docker-compose.yml:/compose/demo.yml
- ./data/wud-store:/store
environment:
- TZ=Europe/Amsterdam
- WUD_LOG_LEVEL=info
- WUD_TRIGGER_DOCKERCOMPOSE_DEMO_FILE=/compose/demo.yml
- WUD_TRIGGER_DOCKERCOMPOSE_DEMO_THRESHOLD=minor
- WUD_TRIGGER_DOCKERCOMPOSE_DEMO_PRUNE=true
- WUD_TRIGGER_DOCKERCOMPOSE_DEMO_AUTO=true
security_opt:
- no-new-privileges=true
read_only: true

Net als bij Watchtower wordt de Docker-socket /var/run/docker.sock in de container gemount met leesrechten. Daardoor kan WUD alle draaiende containers herkennen. De Compose-bestanden van de containers die WUD moet updaten (hier ./demo/docker-compose.yml) worden ook doorgegeven aan de WUD-container als bind-mounts.

Lees dit artikel verder

Lees over tech-trends en achtergronden, nieuwe apparatuur, software en toepassingen voor professioneel gebruik. Met c’t heb je altijd de juiste tech-informatie. Word abonnee en lees onbeperkt alle artikelen.
Bekijk abonnementen Al abonnee? Log in

Het gedrag van de auto-updater wordt geregeld via omgevingsvariabelen, de zogenaamde triggers. De trigger DEMO_FILE=/compose/demo.yml wijst naar het gemounte Compose-bestand in de container. De andere variabelen die DEMO bevatten verwijzen allemaal naar dat Compose-bestand.

DEMO_AUTO=true instrueert WUD om automatisch updates uit te voeren. Omdat echter tegelijkertijd DEMO_THRESHOLD=minor ingesteld is, geldt dat alleen voor minor updates (zoals nginx:1.27 naar 1.28) en patchupdates (nginx:1.27.2 naar nginx.1.27.3). Major updates, bijvoorbeeld nginx:1 naar nginx:2, worden wel aangeboden in het dashboard, maar niet uitgevoerd. De trigger DEMO_PRUNE=true verwijdert oude images.

Aan de Compose-bestanden van de containers die WUD onder zijn hoede neemt kunnen labels worden toegevoegd die alleen van toepassing zijn op de betreffende container. In onze voorbeeldapplicatie nginx hebben we de volgende labels ingesteld:

nginx:
image: nginx:1.27.3
labels:
- "wud.tag.include=^\d+\.\d+\.\d+$$"
- "wud.display.name=demo nginx"
- "wud.link.template=https://github.com/nginx/nginx/releases/tag/release-$${major}.$${minor}.$${patch}"

Het label "wud.tag.include=^\d+\.\d+\.\d+$$" bevat een reguliere expressie en sluit tags uit die niet bestaan uit getallen gescheiden door punten, zoals voorgeschreven door semantisch versiebeheer [1]. De tag 1.2.3 zou dus prima zijn, terwijl latest of alpine worden uitgesloten. wud.display.name definieert de naam van de container die wordt weergegeven in de WUD-webinterface en wud.link.template linkt in het WUD-dashboard naar de releasenotes van nieuwe versies.

Zodra je WUD hebt gestart met het commando docker compose up -d, kun je de webinterface van de tool oproepen met het IP-adres van de host en TCP-poort 3000, bijvoorbeeld http://192.168.1.100:3000.

Let op: WUD in de hier getoonde configuratie is geschikt voor gebruik in het eigen netwerk en mag niet toegankelijk zijn vanaf het internet. Voor toegang op afstand moet je een VPN of een (VPN-)tunneloplossing zoals Pangolin gebruiken. We hebben dat beschreven in ons zelfhosting-compendium [2].

De officiële documentatie (zie de link) legt uit hoe je containers op meerdere Docker-hosts automatisch kunt updaten met WUD.

Doco-CD en Renovate

Doco-CD is een lichtgewicht GitOps-tool die Docker Compose-projecten automatisch uitrolt als er iets verandert in de bijbehorende Git-repository. Het controleert de repository (doelstatus) en vergelijkt die met de draaiende containers op de host (actuele status).

Bij afwijkingen, bijvoorbeeld als er een hoger versienummer in de repository verschijnt, downloadt het de nieuwe images en herstart het de containers.

Je hebt Doco-CD nodig op de Docker-host en de Docker Compose-bestanden van je apps in een Git-repository. Dat kan een zelfbeheerde Git-server zijn of je kunt GitHub, GitLab, CodeBerg, Gitea of Forgejo gebruiken. Een voorbeeld van de opbouw vind je in de repository bij dit artikel (zie de link).

Die bevat Docker Compose-bestanden voor de webserver Nginx in de directory webserver en de KV-Cache Redis in de directory database.

Het configuratiebestand .doco-cd.yml bepaalt welke mappen met Compose-bestanden Doco-CD in de gaten moet houden.

name: webserver
working_dir: webserver/
compose_files:
docker-compose.yml
pull: true

name: database
working_dir: database/
compose_files:
docker-compose.yml
pull: true

Doco-CD draait op de Docker-host. Je kunt een webhook van GitHub, GitLab en dergelijke gebruiken om het te informeren over wijzigingen in de repository, maar daarvoor moet je Doco-CD instantie toegankelijk zijn vanaf het internet (of in hetzelfde netwerk zitten als een zelfgehoste Forgejo, GitLab of Gitea).

Als je Doco-CD liever achter slot en grendel houdt, configureer het dan in polling-modus. Het scant de repository dan met ingestelde intervallen op veranderingen en rolt de stack opnieuw uit als dat nodig is. Net als alle andere containers in dit artikel installeer je Doco-CD via Docker Compose:

services:
doco-cd:
container_name: doco-cd
image: ghcr.io/kimdre/doco-cd:0.77.0
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
LOG_LEVEL: info
POLL_CONFIG: |
- url: https://github.com/ndi-ct/doco-cd.git
reference: main
interval: 180

Configureer de te monitoren repository via omgevingsvariabelen in de sectie POLL_CONFIG:. Voor url vul je de URL van je repository in, reference geeft de branch aan en interval specificeert het tijdsinterval in seconden.

Je kunt Doco-CD gebruiken met een openbare repository. Als Doco-CD een private-repository moet scannen, dan moet je een Personal Access Token (PAT) aanmaken bij de GitHub-ontwikkelaarsopties die leestoegang verschaft.

Maak vervolgens een bestand genaamd .env in dezelfde map als het docker-compose.yml-bestand voor Doco-CD met de volgende inhoud:

GIT_ACCESS_TOKEN=github_pat_11ASWWA7A0R

Vervang de token door je eigen token en voeg dan de regel - GIT_ACCESS_ TOKEN=${GIT_ACCESS_TOKEN} toe bij de omgevingsvariabelen van het Compose-bestand voor Doco-CD.

Onthoud dat met een openbare repository iedereen je Docker-infrastructuur kan traceren. Onversleutelde secrets horen niet thuis in een GitHub-repository!

Je kunt secrets opslaan in een bestand genaamd .env op de Docker-host en daar dan naar verwijzen. Als alternatief kun je secrets in de repository versleutelen met SOPS en ze door Doco-CD laten ontsleutelen op de host. In de Doco-CD documentatie (zie de link) kun je lezen hoe dat werkt.

Renovatiewerkzaamheden

Doco-CD rolt uit wat er in de repository staat, maar je moet nog steeds handmatig zorgen voor het versienummer in de Compose-bestanden. Die taak kan worden uitgevoerd door Renovate, een dependency-update-bot. Die scant de Compose-bestanden in het archief, vergelijkt imagetags met beschikbare versies in de registry en maakt automatisch pullrequests aan als er nieuwere versies zijn.

Als je Renovate instelt als een GitHub-app, is het installeren snel gedaan. Open github.com/apps/renovate in je browser, klik op de knop Install en volg de wizard.

Selecteer vervolgens je repository voor Doco-CD. Na de installatie maakt de Renovate-bot een onboarding pullrequest aan. Dat bevat onder andere een configuratiebestand met de naam renovate.json. Wanneer je de pullrequest bevestigt, wordt de bot actief. Als hij verouderde containers vindt, stelt hij voor om die te updaten via een pullrequest.

In de standaardconfiguratie moet je die allemaal goedkeuren, maar je kunt in renovate.json ook aangeven dat Renovate automatisch pullrequests voor patch- en minor updates moet mergen.

{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended"
],
"packageRules": [
{
"matchDatasources": ["docker"],
"matchUpdateTypes": ["minor", "patch"],
"automerge": true
}
]
}

De combinatie van Doco-CD en Renovate-bot creëert een volwaardige updatepipeline voor Docker Compose.

Renovate maakt de PR aan met het nieuwe versienummer, je controleert die zelf en accepteert een merge (of laat het automatisch mergen). Doco-CD ziet die verandering tijdens de volgende pollingcyclus en rolt de bijgewerkte stack uit. Elke wijziging wordt gedocumenteerd als een commit en een rollback is kinderspel, bijvoorbeeld met het commando git revert.

Conclusie

Als je Watchtower niet langer kunt gebruiken, maar tevreden bent met de manier waarop het werkt, dan kun je overstappen naar de fork nicholas-fedor/watchtower.

Als je meer controle over updates wilt, dan is WUD een goed alternatief dat ook de Compose-bestanden kan bijwerken en je in staat stelt om weloverwogen beslissingen te nemen.

Als je grotere plannen hebt en bereid bent om je Compose-bestanden in een Git-repository te zetten, dan zijn Doco-CD en Renovate een mooi duo dat GitOps voor Docker Compose mogelijk maakt.

De hoeveelheid werk neemt toe met elke volgende oplossing, maar de controle en transparantie ook. Welke aanpak de juiste is hangt af van hoeveel invloed je aan de automatisering wilt geven en hoeveel slaap je verliest als een nachtelijke update fout gaat.

Niklas Dierking en Marco den Teuling

Literatuur

[1] Jan Mahn en Marco den Teuling, Waarom versienummers niet willekeurig zijn, c’t 3/2022, p.83
[2] Niklas Dierking en Noud van Kruysbergen, Diensten met reverse-proxy of (VPN-)tunnel beschikbaar maken, c’t 10/2025, p.42

Inspiratie in je mailbox

Blijf bij op IT-gebied en verbreed je expertise. Ontvang elke week artikelen over de laatste tech-ontwikkelingen, toepassingen, nieuwe hard- en software én ontvang tips en aanbiedingen.

Loginmenu afsluiten