Docker-Container-Updates richtig automatisieren: Watchtower für Auto-Updates oder Diun für Benachrichtigungen. Vergleich, Setup und Strategie für sicheres Patch-Management.
💡 Hinweis: Dieses Tutorial setzt voraus, dass du Docker auf Debian 13 installiert hast und mehrere Container betreibst. Ein Discord- oder Telegram-Webhook wird empfohlen — Setup zeigen wir.
Einleitung — Warum automatisierte Container-Updates?
Wer Self-Hosting betreibt, kennt das Problem: Pro Container ein Repository, pro Update ein docker compose pull. Bei zwanzig Containern wird das schnell zur Pflicht-Übung — oder wird vergessen, was schlimmer ist. Veraltete Container sind ein Top-Sicherheitsrisiko: Ein ungepatcher Vaultwarden, eine alte Nextcloud-Version mit bekannten CVEs, ein veraltetes Authentik mit Auth-Bypass — alles realistische Szenarien.
Es gibt zwei sinnvolle Ansätze, um das in den Griff zu kriegen:
- Watchtower — Updates automatisch installieren, ohne dass ihr eingreift
- Diun — Benachrichtigung bei verfügbaren Updates, manuelles Update bleibt euer Job
Beide haben ihre Daseinsberechtigung. Wir zeigen beide Setups und am Ende, wie ihr sie sinnvoll kombiniert.
Watchtower vs. Diun — Direktvergleich
| Feature | Watchtower | Diun |
|---|---|---|
| Auto-Update | Ja | Nein |
| Benachrichtigung | Ja | Ja (Hauptzweck) |
| Pre-Update-Backup | Manuell konfigurierbar | Nicht relevant |
| Selektives Update | Per Label | Per Label |
| Image-Registry-Support | Docker Hub, GHCR, etc. | Docker Hub, GHCR, etc. |
| Konfiguration | Compose + Env Vars | YAML-Konfigfile |
| Rollback | Nein (Tag-Pinning manuell) | n.v. |
| Beste Wahl für | Homelab ohne Downtime-Risiko | Produktion mit Audit-Pflicht |
⚠️ Wichtig: Auto-Update klingt verlockend, ist aber für kritische Production-Setups riskant. Eine breaking Change in einem Major-Update kann eure Cloud, Authentication oder Datenbank zerlegen. Für Vaultwarden, Authentik und Nextcloud empfehlen wir Diun-Notifications + manuelles Update statt Watchtower-Auto-Update.
Variante A: Watchtower (Auto-Update)
Watchtower überwacht laufende Container, vergleicht ihre Image-Hashes mit den Registry-Versionen und führt bei Updates automatisch docker pull + recreate aus.
Schritt 1: Watchtower mit Discord-Notifications
sudo mkdir -p /opt/watchtower
sudo nano /opt/watchtower/docker-compose.ymlInhalt:
services:
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /etc/localtime:/etc/localtime:ro
environment:
# Nur Container mit dem Label "com.centurylinklabs.watchtower.enable=true" updaten
WATCHTOWER_LABEL_ENABLE: "true"
# Updates jeden Tag um 4:00 Uhr (Cron-Format mit Sekunden)
WATCHTOWER_SCHEDULE: "0 0 4 * * *"
# Alte Images aufräumen
WATCHTOWER_CLEANUP: "true"
# Rolling Updates statt alle gleichzeitig
WATCHTOWER_ROLLING_RESTART: "true"
# Discord-Notifications
WATCHTOWER_NOTIFICATIONS: shoutrrr
WATCHTOWER_NOTIFICATION_URL: "discord://EUER_DISCORD_WEBHOOK_TOKEN@EURE_CHANNEL_ID"
WATCHTOWER_NOTIFICATIONS_LEVEL: info
# Format der Nachrichten
WATCHTOWER_NOTIFICATION_TEMPLATE: |
{{- if .Report -}}
{{- with .Report -}}
{{ len .Updated }}/{{ len .Scanned }} updated.
{{- range .Updated }}
- {{ .Name }} ({{ .ImageName }}): {{ .CurrentImageID.ShortID }} → {{ .LatestImageID.ShortID }}
{{- end }}
{{- end }}
{{- end }}Schritt 2: Discord-Webhook konfigurieren
Das Format der WATCHTOWER_NOTIFICATION_URL ist:
discord://TOKEN@CHANNEL_IDDen Wert bekommt ihr aus der Discord-Webhook-URL:
https://discord.com/api/webhooks/CHANNEL_ID/TOKENFür Telegram:
telegram://BOT_TOKEN@telegram?chats=CHAT_IDFür E-Mail:
smtp://user:password@smtp.example.com:587/?fromAddress=from@example.com&toAddresses=to@example.comEine vollständige Liste der unterstützten Notification-Provider findet ihr im Shoutrrr-Projekt.
Schritt 3: Container, die geupdatet werden sollen, markieren
Nur Container mit dem Label com.centurylinklabs.watchtower.enable=true werden geupdatet. Beispiel:
services:
whoami:
image: traefik/whoami
labels:
- "com.centurylinklabs.watchtower.enable=true"Schritt 4: Watchtower starten
cd /opt/watchtower
sudo docker compose up -d
sudo docker logs -f watchtowerBei Watchtower 1.x.x und Scheduling first run: ... läuft alles.
✅ Geschafft! Watchtower überwacht eure Container und updatet sie nachts automatisch. Discord bekommt nach jedem Lauf einen Status-Report.
Sofortiges Update auslösen — manuell
sudo docker exec watchtower /watchtower --run-once --label-enableVariante B: Diun (Notification only)
Diun macht kein automatisches Update — es schickt nur eine Benachrichtigung, wenn ein Container-Image eine neuere Version hat. Ihr entscheidet, wann ihr updatet.
Schritt 1: Verzeichnisstruktur
sudo mkdir -p /opt/diun/data
sudo nano /opt/diun/diun.ymlSchritt 2: Diun-Konfiguration
db:
path: /data/diun.db
watch:
workers: 10
schedule: "0 */6 * * *" # alle 6 Stunden prüfen
jitter: 30s
firstCheckNotif: <strong>false</strong>
providers:
docker:
watchByDefault: <strong>false</strong> # nur Container mit Label "diun.enable=true"
watchStopped: <strong>false</strong>
notif:
discord:
webhookURL: "https://discord.com/api/webhooks/CHANNEL_ID/TOKEN"
mentions:
- "@everyone"
renderFields: <strong>true</strong>
timeout: 10sSchritt 3: docker-compose.yml
sudo nano /opt/diun/docker-compose.ymlInhalt:
services:
diun:
image: ghcr.io/crazy-max/diun:latest
container_name: diun
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./data:/data
- ./diun.yml:/diun.yml:ro
environment:
TZ: "Europe/Berlin"
LOG_LEVEL: info
command: serve --config /diun.ymlSchritt 4: Container, die überwacht werden sollen, markieren
services:
vaultwarden:
image: vaultwarden/server:latest
labels:
- "diun.enable=true"Schritt 5: Diun starten
cd /opt/diun
sudo docker compose up -d
sudo docker logs -f diunBeim ersten Lauf indiziert Diun alle markierten Container. Sobald ein Update verfügbar ist, kommt eine Discord-Nachricht.
💡 Tipp: Wenn ihr Diun das erste Mal startet und nicht für jeden bestehenden Container eine Nachricht wollt, lasst
firstCheckNotif: falseaktiv. Dann bekommt ihr nur Notifications für echte zukünftige Updates.
Variante C: Die Kombination — empfohlene Strategie
Die meisten Self-Hoster brauchen einen Mittelweg:
- Unkritische Container (Tools, Test-Setups, Development) → Watchtower-Auto-Update
- Kritische Container (Datenbanken, Authentication, Cloud) → Diun-Notification + manuelles Update
So baut ihr beides parallel:
In den Labels jedes Containers entscheidet ihr, welcher Mechanismus greift:
services:
# Auto-Update via Watchtower
whoami:
image: traefik/whoami
labels:
- "com.centurylinklabs.watchtower.enable=true"
# Notification-only via Diun
authentik-server:
image: ghcr.io/goauthentik/server:2025.10
labels:
- "diun.enable=true"
# Kein Watchtower-Label — Watchtower lässt diesen Container in RuheBeide Tools laufen parallel, jedes prüft nur seine eigenen markierten Container.
💡 Empfehlung: Aus Erfahrung — pinnt kritische Container immer auf eine konkrete Major.Minor-Version (z.B.
authentik:2025.10stattauthentik:latest). Damit greift Auto-Update nur für Patch-Releases, nicht für Major-Updates mit potenziellen Breaking Changes.
Schritt 6: Pre-Update-Backups (für Watchtower)
Watchtower kann vor jedem Update ein Lifecycle-Hook ausführen — perfekt für ein Quick-Backup.
In den Labels eines Containers:
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "com.centurylinklabs.watchtower.lifecycle.pre-update=/backup.sh"
- "com.centurylinklabs.watchtower.lifecycle.post-update=/cleanup.sh"Im Container muss /backup.sh ausführbar sein. Beispiel-Script:
#!/bin/bash
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
mysqldump --single-transaction nextcloud | gzip > /backups/pre-update-$TIMESTAMP.sql.gz⚠️ Best Practice: Pre-Update-Hooks sind besonders bei Datenbanken Gold wert. Falls ein Update fehlschlägt, habt ihr immer einen frischen Snapshot, mit dem ihr in Sekunden zurückrollen könnt.
Schritt 7: Tag-Strategie verstehen
Die meisten Update-Probleme kommen aus falschen Tags:
| Tag | Verhalten | Empfehlung |
|---|---|---|
:latest | Immer neueste Version, auch Major-Updates | Nur für unkritische Container |
:1 | Höchste Version 1.x.x | Mittel-Risiko |
:1.2 | Höchste Version 1.2.x | Empfohlen für kritische Apps |
:1.2.3 | Genau diese Version | Maximale Stabilität, manuelle Updates nötig |
Beispiele:
# Riskant: Watchtower würde 2.x → 3.x mitnehmen
image: postgres:latest
# Sicher: Watchtower bleibt bei Postgres 16, holt aber Patches (16.1 → 16.2 → 16.3)
image: postgres:16
# Maximal sicher: Keine Updates ohne explizite Änderung
image: postgres:16.4-alpine💡 Tipp: Für Datenbanken (PostgreSQL, MariaDB, MongoDB) immer auf Major.Minor pinnen. Ein automatischer Sprung von
postgres:15aufpostgres:16würde eure DB beim ersten Restart in einen inkompatiblen State bringen.
Zusammenfassung & Checkliste
| Schritt | Status |
|---|---|
| Discord/Telegram-Webhook eingerichtet | ☐ |
| Watchtower oder Diun installiert | ☐ |
| Notification-Test erfolgreich | ☐ |
| Container mit Labels markiert | ☐ |
| Tags auf Major.Minor gepinnt (kritische Apps) | ☐ |
| Pre-Update-Backup-Hook (optional) | ☐ |
| Test-Update durchgeführt | ☐ |
| Update-Strategie dokumentiert | ☐ |
Troubleshooting
Watchtower updatet nicht
- Container hat das Label
com.centurylinklabs.watchtower.enable=true? - Watchtower läuft mit
WATCHTOWER_LABEL_ENABLE=true? - Schedule-Format korrekt? Watchtower nutzt 6-Felder-Cron (mit Sekunden!)
- Logs prüfen:
sudo docker logs watchtower
Diun sendet keine Notifications
webhookURLkorrekt? Test:curl -X POST -H "Content-Type: application/json" -d '{"content":"test"}' EURE_WEBHOOK_URLfirstCheckNotif: falseaktiv? Dann gibt es bei der ersten Run keine Nachricht- Nur ein Container markiert? Diun loggt das beim Start
Watchtower startet Container, aber App ist kaputt
- Tag auf
:latestund Major-Update kam? - Container braucht Migration-Step? Manche Apps (z.B. Nextcloud) brauchen
occ upgradenach Image-Update - Lösung: Auf Major.Minor pinnen oder zu Diun wechseln
„no space left on device“
- Watchtower-
WATCHTOWER_CLEANUP=trueaktiv? Räumt alte Images auf - Manuell:
sudo docker system prune -a(Vorsicht — auch ungenutzte Volumes weg, falls--volumes)
Image kann nicht gepullt werden — Authentication
Bei privaten Registries:
volumes:
- /home/youruser/.docker/config.json:/config.jsonWatchtower / Diun nutzen diese Credentials dann automatisch.
Nächste Schritte
- Backup-Strategie mit restic — Pre-Update-Backups in S3
- Renovate Bot — Image-Tags in Compose-Files automatisch aktualisieren (Pull-Request-basiert)
- Komodo / Portainer — Container-Management mit Update-Approval-Workflow
- Trivy / Grype Image-Scanning — CVEs in Images vor Deployment finden
Habt ihr Fragen oder Probleme? Schreibt es in die Kommentare — ich helfe gerne!