WUD statt Watchtower: Docker-Container automatisch aktualisieren
Watchtower ist eingestellt. Diese Anleitung richtet WUD (What's Up Docker) 9.4.1 per Docker Compose ein: Opt-in per Label, automatische Updates für freigegebene Stacks, Benachrichtigungen, Schutz für Datenbanken und Umstieg von Watchtower.
Geprüft am 14.10.2026 · für WUD 9.4.1
Mit KI erstellt – redaktionelle Prüfung ausstehend
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Watchtower war jahrelang die bequemste Lösung, um Docker-Container automatisch zu aktualisieren. Das Projekt containrrr/watchtower ist inzwischen eingestellt: Das GitHub-Repository ist archiviert, das letzte Release 1.7.1 stammt von 2023. Als Ersatz beschreibt diese Anleitung WUD (What's Up Docker). WUD erkennt neue Image-Versionen, zeigt sie in einer Weboberfläche an, benachrichtigt Sie und aktualisiert auf Wunsch genau die Container, die Sie freigeben. Wer noch Watchtower betreibt, findet in Schritt 1 und Schritt 7 den Umstieg.
Voraussetzungen
- Linux-Server oder Mini-PC mit Docker Engine und Compose-Plugin, x86_64 oder ARM64 (das Image gibt es für beide Architekturen)
- Ressourcen: WUD selbst belegte im Test rund 85 MB RAM; 1 CPU-Kern und 512 MB freier RAM reichen neben Ihren Diensten, das Image braucht rund 560 MB Platz
- Root- oder sudo-Zugriff, denn WUD braucht den Docker-Socket
/var/run/docker.sock - Ihre Stacks liegen in einem gemeinsamen Ordner, in dieser Anleitung
/opt/stacks/NAME/compose.yaml - Für Benachrichtigungen ein ntfy-Server oder ein anderer Kanal (Telegram, E-Mail, Gotify)
| Eckdaten | Wert |
|---|---|
| Image | getwud/wud:9.4.1 (alternativ ghcr.io/getwud/wud:9.4.1) |
| Port | 3000 (Weboberfläche und API) |
| Volumes | /var/run/docker.sock, ./store:/store, /opt/stacks:/opt/stacks |
| Wichtige Variablen | WUD_AUTH_ADMIN_USER, WUD_AUTH_ADMIN_PASSWORD, WUD_WATCHER_LOCAL_*, WUD_TRIGGER_* |
Schritt 1: Watchtower entfernen
Laufen Watchtower und WUD gleichzeitig, greifen zwei Werkzeuge auf dieselben Container zu. Entfernen Sie Watchtower deshalb zuerst. Lag Watchtower in einem eigenen Compose-Projekt, beenden Sie es dort:
cd /opt/watchtower
docker compose down
# oder bei einem per docker run gestarteten Container:
docker rm -f watchtower
docker image rm containrrr/watchtower:latest
Es gibt einen zweiten Grund, nicht zu warten: Im Test auf Docker Engine 29.8 startete containrrr/watchtower:latest (Version 1.7.1) gar nicht mehr. Das Log meldete client version 1.25 is too old. Minimum supported API version is 1.40, danach brach der Prozess mit einem Panic ab. Auf aktuellen Docker-Versionen aktualisiert Watchtower also nichts mehr, auch wenn der Container in alten Compose-Dateien noch steht.
Verifizieren: docker ps -a --filter name=watchtower gibt keine Zeile mehr aus.
Schritt 2: Projektordner und compose.yaml anlegen
Legen Sie einen Ordner für WUD an und darin eine Datei .env mit dem Administratorpasswort. Ein Doppelpunkt im Passwort ist laut Dokumentation nicht erlaubt.
sudo mkdir -p /opt/wud && cd /opt/wud
echo "WUD_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -d ':/+=')" | sudo tee .env
sudo chmod 600 .env
Die compose.yaml:
services:
wud:
image: getwud/wud:9.4.1
container_name: wud
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./store:/store
- /opt/stacks:/opt/stacks
environment:
- TZ=Europe/Berlin
- WUD_AUTH_ADMIN_USER=admin
- WUD_AUTH_ADMIN_PASSWORD=${WUD_ADMIN_PASSWORD}
# Opt-in: nur Container mit wud.watch=true
- WUD_WATCHER_LOCAL_WATCHBYDEFAULT=false
- WUD_WATCHER_LOCAL_CRON=0 4 * * *
# Automatische Updates für Compose-Stacks, nur nach Freigabe
- WUD_TRIGGER_DOCKERCOMPOSE_STACKS_INCLUDEBYDEFAULT=false
- WUD_TRIGGER_DOCKERCOMPOSE_STACKS_BACKUP=true
- WUD_TRIGGER_DOCKERCOMPOSE_STACKS_PRUNE=true
# Benachrichtigung für alle überwachten Container
- WUD_TRIGGER_NTFY_INFO_URL=https://ntfy.example.de
- WUD_TRIGGER_NTFY_INFO_TOPIC=docker-updates
labels:
- wud.watch=true
- wud.trigger.exclude=dockercompose.stacks
Die wichtigsten Punkte: Ohne WUD_WATCHER_LOCAL_WATCHBYDEFAULT=false überwacht WUD wie früher Watchtower jeden Container. Der Cron-Ausdruck legt die tägliche Prüfung auf 4 Uhr. Der Ordner /opt/stacks wird unter demselben Pfad eingebunden, denn der Compose-Trigger liest den Pfad der compose.yaml aus den Labels, die Docker Compose an jeden Container hängt. WUD überwacht sich selbst, aktualisiert sich aber nicht selbst; das erledigen Sie bewusst per Hand.
Verifizieren: docker compose config --quiet gibt nichts aus, die Datei ist also gültig, und cat .env zeigt ein Passwort ohne Doppelpunkt.
Schritt 3: WUD starten und anmelden
docker compose up -d
docker compose logs wud | grep -E "starting|watched|listening"
Im Test meldete das Log WUD is starting (version = 9.4.1), Server listening on port 3000 und nach dem ersten Lauf Cron finished (3 containers watched, 0 errors, 2 available updates). Beim ersten Start prüft WUD sofort, danach nach Zeitplan. Das Passwort legt WUD gehasht in der SQLite-Datenbank unter ./store ab; dieser Ordner gehört ins Backup.
Öffnen Sie http://SERVER-IP:3000 und melden Sie sich als admin an. Die Startseite zeigt Container, Trigger, Watcher und Registries im Überblick.

Ohne Anmeldung ist auch die API gesperrt. Das prüfen Sie direkt auf dem Server:
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/health
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:3000/api/containers
curl -s -o /dev/null -w "%{http_code}\n" -u "admin:$(grep -oP '(?<==).*' .env)" http://localhost:3000/api/containers
Verifizieren: docker compose ps zeigt wud als healthy. Die drei curl-Aufrufe liefern im Test 200, 401 und 200; mit falschem Passwort ebenfalls 401. Stellen Sie Port 3000 nicht ungeschützt ins Internet, sondern nutzen Sie VPN oder einen Reverse Proxy mit HTTPS.
Schritt 4: Container per Label freigeben
WUD arbeitet mit zwei Bausteinen: Der Watcher findet neue Versionen, ein Trigger handelt (benachrichtigen oder aktualisieren). Welche Container überwacht werden und welche Trigger für sie gelten, steuern Sie per Label in der compose.yaml des jeweiligen Stacks. Ein Beispiel mit Webserver und Datenbank in /opt/stacks/app/compose.yaml:
services:
web:
image: nginx:1.27.0-alpine
labels:
- wud.watch=true
- wud.tag.include=^1\.27\.\d+-alpine$$
- wud.trigger.include=dockercompose.stacks
db:
image: postgres:16.4-alpine
labels:
- wud.watch=true
- wud.tag.include=^16\.\d+-alpine$$
wud.tag.include ist ein regulärer Ausdruck für die erlaubten Tags. So bleibt nginx bei 1.27.x und PostgreSQL in Major-Version 16. Das doppelte $$ ist Pflicht, sonst hält Docker Compose das Dollarzeichen für eine Variable. Container ohne Label ignoriert WUD; im Test tauchte ein dritter Container ohne Label nicht in der Liste auf. Einen Ad-hoc-Lauf starten Sie in der Containerliste mit WATCH NOW.

Verifizieren: Unter Containers stehen nur Ihre markierten Container. Im Test erkannte WUD für postgres:16.4-alpine das neuere 16.15-alpine und ordnete das Update als minor ein.
Schritt 5: Automatische Updates per Trigger
Der Trigger dockercompose.stacks aus Schritt 2 gilt wegen INCLUDEBYDEFAULT=false nur für Container mit wud.trigger.include=dockercompose.stacks. Findet WUD für einen solchen Container einen passenden Tag, zieht es das Image, ersetzt den Container und schreibt den neuen Tag in die compose.yaml. Mit BACKUP=true bleibt die alte Fassung als compose.yaml.back liegen, PRUNE=true löscht das alte Image.
Im Test lief genau das direkt nach dem Start: nginx:1.27.0-alpine wurde auf 1.27.5-alpine gehoben, nicht auf eine neuere 1.29, weil der Tag-Filter greift. Das Log zeigt die Kette Pull image nginx:1.27.5-alpine, recreated on new image with success und Image nginx:1.27.0-alpine removed with success.
Für Container, die per docker run gestartet wurden, gibt es den Docker-Trigger. Ergänzen Sie dafür in der WUD-compose.yaml:
- WUD_TRIGGER_DOCKER_EINZELN_INCLUDEBYDEFAULT=false
- WUD_TRIGGER_DOCKER_EINZELN_PRUNE=true
und starten Sie den Container mit --label wud.watch=true --label wud.trigger.include=docker.einzeln. Updates lassen sich auch von Hand anstoßen: In der Containerliste das Menü am Zeilenende öffnen, Update container wählen und mit UPDATE bestätigen.

Verifizieren: docker ps zeigt den Container mit dem neuen Tag, diff compose.yaml.back compose.yaml im Stack-Ordner zeigt nur die geänderte image-Zeile. Im Test lief der Container danach mit traefik/whoami:v1.12.0, die compose.yaml enthielt nginx:1.27.5-alpine.
Schritt 6: Benachrichtigungen und Datenbanken absichern
Der ntfy-Trigger ntfy.info hat kein INCLUDEBYDEFAULT=false und meldet deshalb die Funde aller überwachten Container, die kein wud.trigger.include tragen. Das Label wud.trigger.include wirkt laut Dokumentation als ausschließliche Liste: Der nginx-Container aus Schritt 4 bekommt damit nur den Compose-Trigger und keine ntfy-Meldung. Soll ntfy auch für automatisch aktualisierte Container melden, ersetzen Sie dort das Label durch wud.trigger.dockercompose.stacks.enabled=true; diese Einzelfreigabe lässt die übrigen Trigger unberührt. Im Test kam auf dem Topic die Nachricht Container app-db-1 running with tag 16.4-alpine can be updated to tag 16.15-alpine an. Wie Sie einen eigenen ntfy-Server aufsetzen, zeigt ntfy mit Docker installieren. Für Telegram heißen die Variablen WUD_TRIGGER_TELEGRAM_NAME_BOTTOKEN und WUD_TRIGGER_TELEGRAM_NAME_CHATID.
Datenbanken bekommen bewusst kein wud.trigger.include. Ein automatischer Sprung auf eine neue Major-Version von PostgreSQL oder MariaDB kann das Datenverzeichnis unbrauchbar machen. Sichern Sie vor jedem Datenbank-Update, siehe MySQL- und PostgreSQL-Backup automatisieren, und aktualisieren Sie per Hand mit docker compose pull db && docker compose up -d db.

Verifizieren: Ein Klick auf den Datenbank-Container und den Reiter Triggers zeigt nur Ntfy Info. Im Test blieb postgres:16.4-alpine unverändert, obwohl 16.15 bereitstand.
Schritt 7: Watchtower-Labels und Einstellungen umstellen
Watchtower arbeitete standardmäßig nach dem Prinzip „alles aktualisieren, Ausnahmen markieren“, WUD in dieser Anleitung umgekehrt. Übertragen Sie Ihre alten Einstellungen so:
| Watchtower | WUD |
|---|---|
com.centurylinklabs.watchtower.enable=true | wud.watch=true plus wud.trigger.include=dockercompose.stacks |
com.centurylinklabs.watchtower.enable=false | kein Label (mit WATCHBYDEFAULT=false) |
nur melden (--monitor-only) | wud.watch=true ohne Update-Trigger |
WATCHTOWER_SCHEDULE, WATCHTOWER_POLL_INTERVAL | WUD_WATCHER_LOCAL_CRON |
WATCHTOWER_CLEANUP=true | WUD_TRIGGER_..._PRUNE=true |
WATCHTOWER_NOTIFICATION_URL | eigener Trigger je Kanal (ntfy, Telegram, SMTP) |
Alte com.centurylinklabs.watchtower.*-Labels stören WUD nicht; im Test trug der nginx-Container noch das alte Label und wurde nur nach den WUD-Labels behandelt. Entfernen Sie sie trotzdem beim nächsten Bearbeiten, damit die Dateien eindeutig bleiben. Nach jeder Label-Änderung den Stack mit docker compose up -d neu erstellen, sonst sieht WUD die alten Labels.
Verifizieren: grep -rl centurylinklabs /opt/stacks findet nach dem Aufräumen keine Datei mehr, und die WUD-Containerliste zeigt dieselben Container, die vorher Watchtower aktualisiert hat.
Troubleshooting
- Compose-Trigger tut nichts, Log meldet
Compose file /opt/stacks/... does not exist: Der Stack-Ordner ist nicht oder unter einem anderen Pfad in WUD eingebunden. Im Test provoziert: Ohne Mount blieb der Container auf dem alten Tag. Pfad im Container identisch zum Host einbinden. - Warnung
unable to delete ... (must be forced)beim Prune: Ein anderer Container nutzt das alte Image noch. Das Update selbst war erfolgreich; das Image bleibt, bis es niemand mehr verwendet. - API liefert 401: Falscher Benutzer oder Passwort mit Doppelpunkt. Passwort in
.envändern,docker compose up -d; WUD übernimmt es beim Start (Ensuring administrator role and updating credentials). - WUD überwacht alle Container:
WUD_WATCHER_LOCAL_WATCHBYDEFAULT=falsefehlt. - Tag-Filter wirkt nicht: In der compose.yaml fehlt das doppelte
$$am Ende des Ausdrucks. - Neuer Container erscheint nicht: In der Containerliste WATCH NOW klicken oder bis zum nächsten Cron-Lauf warten.
Häufige Fragen
Kann ich Watchtower einfach weiterlaufen lassen?
Nein. Das Original bekommt keine Updates mehr und startete im Test auf Docker Engine 29 nicht, weil es eine zu alte Docker-API anspricht.
Aktualisiert WUD sich selbst?
Nur, wenn Sie WUD_TRIGGER_DOCKER_NAME_SELFUPDATE=true setzen. In dieser Anleitung ist WUD vom Update-Trigger ausgenommen; Sie aktualisieren mit docker compose pull && docker compose up -d im Ordner /opt/wud.
Beim Wechsel von WUD 9.3.0 auf 9.4.1 sichern Sie zuerst den Store-Ordner und die Compose-Datei. Ändern Sie anschließend den Image-Tag und führen Sie docker compose pull wud sowie docker compose up -d wud aus. Version 9.4.1 enthält unter anderem Korrekturen für Container-Neuerstellung mit Docker 29 und für parallele Updates desselben Compose-Projekts. Im Praxistest antwortete der Healthcheck nach dem Upgrade und nach einer Neuinstallation mit HTTP 200; die Container-API lieferte ohne Anmeldung HTTP 401 und mit dem Administratorkonto HTTP 200. Neue Registry-Webhooks müssen Sie für diesen Updateweg nicht aktivieren.
Braucht WUD eine Datenbank?
Nein. Benutzer, Sitzungen und Zustand liegen in ./store/wud.sqlite. Sichern Sie den Ordner zusammen mit der compose.yaml und der .env.
Was ist mit Containern auf :latest?
Ohne Versionsnummer kann WUD nur den Digest vergleichen (Label wud.watch.digest=true). Besser sind feste Tags wie 1.27.5-alpine, dann sehen Sie in Meldungen, was sich ändert.
Fazit
WUD ersetzt Watchtower und ist dabei vorsichtiger: Es überwacht nur freigegebene Container, aktualisiert nur dort, wo Sie einen Trigger zuordnen, und hält Tag-Sprünge per Regex im Rahmen. Im Test erkannte WUD 9.4.1 veraltete Tags zuverlässig, hob einen Compose-Stack samt compose.yaml an, aktualisierte einen Einzelcontainer per Klick und meldete die Datenbank nur. Der Preis dafür sind ein paar Labels pro Stack und der Mount des Stack-Ordners.
Weiterführende Anleitungen und Quellen
- Docker-Updates nach Watchtower: Diun, WUD und Renovate im Vergleich
- Docker Compose Grundlagen und Stacks
- ntfy mit Docker installieren
- MySQL- und PostgreSQL-Backup automatisieren
- WUD-Dokumentation: Quick start, Docker-Compose-Trigger, Container-Labels
- WUD 9.4.1 auf GitHub
- containrrr/watchtower (archiviert)


