Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung
Teil 4 von 7 der Reihe Homelab auf dem Raspberry Pi

Management Summary
Ein Heimserver kann mehrere lokale Dienste über einen gemeinsam verwalteten Zugang bereitstellen. Der beschriebene Aufbau leitet Browseranfragen zur passenden Anwendung, erneuert Zertifikate für verschlüsselte Verbindungen und meldet verfügbare Softwareupdates. Diese Automatisierung erleichtert die Pflege kleiner Installationen auf einem Raspberry Pi. Die Aufgaben bleiben verschieden: Eine Update-Meldung installiert noch keine Korrektur. Ein einzelnes Gerät bleibt außerdem ausfallgefährdet; gespeicherte Daten brauchen wiederherstellbare Sicherungen.
Inhalt
Ein Heimserver mit klar verteilten Aufgaben
Traefik leitet eingehende Anfragen an Docker-Container weiter und kann TLS-Zertifikate über Let’s Encrypt beziehen und erneuern. TLS verschlüsselt die Verbindung zwischen Browser und Traefik. Docker Compose hält die Dienstkonfiguration in einer Datei fest. Watchtower kann Container-Images auf Änderungen prüfen. Das verringert Routinearbeit; Sicherungen, Überwachung und bewusst geplante Updates bleiben erforderlich.
Das folgende Beispiel dient als Ausgangspunkt für einen getrennten Testaufbau auf einem Raspberry Pi mit Docker Engine und Compose. Image-Architektur, Docker-API-Kompatibilität und die gewählten Versionen müssen zum Zielsystem passen. Ein einzelner Pi mit jeweils einem Anwendungscontainer bietet keine Hochverfügbarkeit.

1. DNS, Images und Zertifikatsspeicher vorbereiten
HTTP-01 benötigt eine administrativ kontrollierte Domain und einen aus dem Internet erreichbaren Port 80. Öffentliche A-/AAAA-Einträge, Portweiterleitung und IPv4-/IPv6-Firewallregeln müssen zusammenpassen. Die Host-Ports 80 und 443 müssen frei sein. DNS-01 ermöglicht Zertifikate ohne eingehende Verbindung, macht einen Server hinter CGNAT aber nicht erreichbar. Bei CGNAT teilen mehrere Anschlüsse eine öffentliche IPv4-Adresse des Internetanbieters; eine gewöhnliche Portweiterleitung am Heimrouter genügt dann nicht.
In einem beschreibbaren Projektordner legen die folgenden Befehle den Zertifikatsspeicher an, ohne vorhandene Dateien zu leeren. Neben Dateirechten 600 benötigt der Containerprozess passende Eigentumsrechte. Die Dateien enthalten private Schlüssel und gehören in geschützte Sicherungen.
mkdir -p data
touch data/acme-staging.json data/acme-production.json
chmod 600 data/acme-staging.json data/acme-production.jsonDie Hauptkonfiguration erhält den Namen compose.yaml. Eine benachbarte .env definiert TRAEFIK_IMAGE, SOCKET_PROXY_IMAGE, WHOAMI_IMAGE, ACME_EMAIL und APP_HOST. Die Image-Werte sind vollständige Referenzen auf getestete Versionen von traefik, ghcr.io/tecnativa/docker-socket-proxy und traefik/whoami, möglichst mit dokumentierten Digests. Ein Digest ist ein aus dem Inhalt berechneter Prüfwert, der das genaue Image festlegt statt einer veränderbaren Versionsbezeichnung. Als Hostname dient eine eigene Test-Subdomain ohne Schema oder Pfad. Fehlende Werte brechen Compose ab, statt unbemerkt latest zu verwenden.
2. Anfragen weiterleiten und Docker-Zugriff begrenzen
services:
socket-proxy:
image: ${SOCKET_PROXY_IMAGE:?set tested image reference}
restart: unless-stopped
networks: [control]
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
CONTAINERS: "1"
EVENTS: "1"
NETWORKS: "1"
PING: "1"
VERSION: "1"
POST: "0"
traefik:
image: ${TRAEFIK_IMAGE:?set tested Traefik v3 image reference}
restart: unless-stopped
depends_on: [socket-proxy]
networks: [control, proxy]
ports: ["80:80", "443:443"]
volumes:
- ./data:/data
command:
- --providers.docker=true
- --providers.docker.endpoint=tcp://socket-proxy:2375
- --providers.docker.exposedbydefault=false
- --providers.docker.network=home_proxy
- --entrypoints.web.address=:80
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --entrypoints.websecure.address=:443
- --certificatesresolvers.home.acme.email=${ACME_EMAIL:?set account email}
- --certificatesresolvers.home.acme.storage=/data/${ACME_FILE:-acme-staging.json}
- --certificatesresolvers.home.acme.caserver=${ACME_CA:-https://acme-staging-v02.api.letsencrypt.org/directory}
- --certificatesresolvers.home.acme.httpchallenge.entrypoint=web
whoami:
image: ${WHOAMI_IMAGE:?set tested whoami image reference}
restart: unless-stopped
networks: [proxy]
labels:
traefik.enable: "true"
traefik.http.routers.demo.rule: Host(`${APP_HOST:?set owned test hostname}`)
traefik.http.routers.demo.entrypoints: websecure
traefik.http.routers.demo.tls.certresolver: home
traefik.http.services.demo.loadbalancer.server.port: "80"
com.centurylinklabs.watchtower.enable: "true"
com.centurylinklabs.watchtower.scope: home-demo
networks:
control:
internal: true
proxy:
name: home_proxyNur Traefik veröffentlicht Host-Ports. Die Anwendung teilt das Netzwerk home_proxy mit Traefik; im internen Netzwerk control befinden sich ausschließlich Traefik und der Socket-Proxy. Compose legt beide Netzwerke an. Der feste Netzwerkname muss auf dem Host eindeutig sein oder an beiden Stellen übereinstimmend geändert werden.
Traefik erhält keinen direkten Socket-Mount. Der Proxy erlaubt die aufgeführten Lese-Endpunkte und sperrt schreibende Methoden über POST=0. Auch Lesezugriffe offenbaren Container-Metadaten, möglicherweise einschließlich Umgebungsvariablen. Der Socket-Proxy selbst behält weitreichende Docker-Rechte; Netztrennung und vertrauenswürdige Images bleiben wichtig. Ein Socket-Mount mit :ro allein beschränkt die Docker-API nicht auf Lesezugriffe.
Ein Dashboard wird nicht freigegeben. HTTPS endet bei Traefik; zwischen Traefik und whoami verwendet das Beispiel HTTP. Eine durchgängige TLS-Verschlüsselung liegt damit nicht vor. Der Diagnosedienst whoami gibt Anfrageinformationen zurück und eignet sich nur für einen kurzen Routingtest ohne Zugangsdaten oder vertrauliche Header.
3. Erst Staging prüfen, dann vertrauenswürdige Zertifikate beziehen
docker compose config --quiet prüft die zusammengesetzte Konfiguration. Nach Kontrolle der aufgelösten Werte startet docker compose up -d den Testaufbau. docker compose logs traefik socket-proxy hilft bei der Diagnose von Diensterkennung, abgewiesenen API-Aufrufen und ACME-Fehlern. Abhängig von den gewählten Versionen kann eine Anpassung der erlaubten Lese-Endpunkte nötig sein; pauschaler Schreibzugriff ist keine Lösung.
Voreingestellt ist die Staging-Umgebung von Let’s Encrypt. Deren Zertifikaten vertrauen Browser absichtlich nicht. Nach erfolgreichen Routing- und Challenge-Prüfungen erhalten ACME_CA und ACME_FILE in .env die Werte https://acme-v02.api.letsencrypt.org/directory und acme-production.json. docker compose up -d traefik erstellt Traefik mit der geänderten Konfiguration neu. Staging und Produktion verwenden getrennte Dateien.
Zur Abnahme gehören HTTP-Weiterleitung, HTTPS-Hostname und Zertifikatskette, eine Ablaufüberwachung sowie ein tatsächlicher Anwendungsaufruf von außerhalb des Heimnetzes. Eine gefüllte JSON-Datei allein belegt kein gültiges öffentliches Zertifikat. DNS, Verbindungsprobleme, Dateirechte und Ratenbegrenzungen können die Erneuerung verhindern. Nach dem Test entfällt der Diagnosedienst.
4. Optional eine Update-Prüfung ergänzen
Das ursprüngliche Repository containrrr/watchtower wurde am 17. Dezember 2025 archiviert. Der Fork nicholas-fedor/watchtower veröffentlicht das Image nickfedor/watchtower. Die Auswahl benötigt eine eigene Bewertung von Pflegezustand und Kompatibilität; ein vertrauter Image-Name ist keine Sicherheitsgarantie.
Die optionale Datei monitor.yaml beobachtet nur Container mit Freigabe-Label und dem Geltungsbereich home-demo. Im Beispiel trägt ausschließlich whoami beide Labels. WATCHTOWER_IMAGE muss eine getestete Version referenzieren. docker compose -f compose.yaml -f monitor.yaml up -d ergänzt den Monitor. Bereits vorhandene Watchtower-Instanzen auf dem Host benötigen ebenfalls passende Auswahlregeln.
services:
watchtower:
image: ${WATCHTOWER_IMAGE:?set tested nickfedor/watchtower image reference}
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
WATCHTOWER_MONITOR_ONLY: "true"
WATCHTOWER_LABEL_ENABLE: "true"
WATCHTOWER_SCOPE: home-demo
WATCHTOWER_POLL_INTERVAL: "86400"
WATCHTOWER_CLEANUP: "false"
WATCHTOWER_LABEL_TAKE_PRECEDENCE: "false"
WATCHTOWER_LIFECYCLE_HOOKS: "false"
labels:
com.centurylinklabs.watchtower.enable: "false"
com.centurylinklabs.watchtower.scope: home-demoDieser Modus ersetzt keine Container. Image-Downloads sind weiterhin möglich; Lifecycle-Hooks, also zusätzliche Befehle zu festgelegten Zeitpunkten des Ablaufs, sind ausdrücklich abgeschaltet. Ergebnisse stehen in den Logs; externe Benachrichtigungen benötigen eine eigene Einrichtung und Prüfung. Watchtower behält auch im Beobachtungsmodus den vollständigen Socket-Zugriff. Die Label-Auswahl ist eine Betriebsregel und keine Sicherheitsgrenze.
Für automatisiertes DNS-01 begrenzen eng zugeschnittene DNS-API-Zugangsdaten oder eine delegierte Challenge-Zone die Rechte; unbeschränkte DNS-Zugangsdaten gehören nicht in einen öffentlichen Anwendungscontainer.
Fragen und Antworten
Garantiert eine tägliche Prüfung Patches innerhalb von 24 Stunden?
Nein. Updates hängen von Image-Veröffentlichung, verfolgter Referenz, Registry-Erreichbarkeit und erfolgreicher Ausführung ab. Ein fester Digest folgt keinen neuen Versionen. Ein Versions-Tag kann verändert werden, aber auch ohne weitere Pflege bleiben. Der Monitor installiert nichts; gewählte Versionsreferenzen benötigen bewusste Aktualisierung.
Verhindern automatische Neustarts Ausfallzeiten?
Nein. Der Austausch eines einzelnen Anwendungscontainers unterbricht diese Instanz. Rolling Restarts allein schaffen weder Redundanz noch eine Datenmigration. Automatische Updates benötigen eine ausdrückliche Auswahl, geprüfte Zustandskontrollen, Sicherungen und ein Rückkehrverfahren für Image und Daten. Ein altes Image genügt nach einer inkompatiblen Datenbankmigration nicht.
Reicht eine IP-Freigabeliste für das Dashboard?
Das Beispiel veröffentlicht kein Dashboard. Ein späterer Verwaltungszugang benötigt Authentifizierung und beschränkten Zugriff, etwa über VPN. IP-Regeln hängen von der tatsächlichen Quelladresse und vertrauenswürdigen vorgeschalteten Proxys ab; breite private Adressbereiche belegen keine Identität.
Ist ein Beobachtungslauf vollständig lesend?
Nein. Monitor-only kann Images herunterladen; aktivierte Hooks können Befehle ausführen. Ein zweiter Prozess innerhalb eines laufenden Updaters hält den ursprünglichen Prozess nicht an. --no-pull unterbindet Downloads, ersetzt aber nicht den Beobachtungsmodus.
Quellen
- Docker-Compose-Dokumentation
- Traefik-Dokumentation
- Let’s-Encrypt-Dokumentation
- Traefik-Docker-Anbindung: Endpunkt, Diensterkennung und API-Sicherheit
- Traefik ACME: Speicherung, Testumgebung und Domainprüfung
- Docker Socket Proxy: Endpunktrechte und Trennung
- Watchtower: ursprüngliches Repository archiviert
- Watchtower-Fork und Image
- Watchtower: Label- und Bereichsauswahl
- Watchtower: Beobachtungsmodus und Image-Downloads
- Watchtower: zusätzliche Befehle im Ablauf
- Watchtower: Prüfintervall
- Docker Compose: erforderliche Umgebungsvariablen
- ACME: HTTP-01- und DNS-01-Prüfung
Homelab auf dem Raspberry Pi
- Raspberry Pi 4 und 5: Vom SSD-Laufwerk booten über den Bootloader
- USV für Raspberry Pi: fünf Lösungen und Auswahlkriterien
- Lokales CI/CD für den Raspberry Pi: Automatisierung von Docker-Compose-Deployments
- Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung
- Jellyfin auf Raspberry Pi 5: Direct Play und Grenzen der Transkodierung
- Raspberry Pi als gehärtetes WireGuard-VPN-Gateway mit Split-Tunneling
- Raspberry Pi mit Prometheus und Grafana überwachen