Pi-hole mit Docker: netzwerkweiter Werbe- und Tracker-Blocker
Pi-hole mit Docker Compose betreiben und Werbung sowie Tracker im ganzen Netz per DNS blockieren: compose.yaml, Port-53-Konflikt, Web-Admin, Blocklisten, Update und Backup. Getestet mit Pi-hole 2026.09.0.
Geprüft am 29.09.2026 · für pi-hole 2026.09.0
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

Pi-hole blockiert Werbe- und Tracker-Domains auf DNS-Ebene und schützt damit alle Geräte im Netz, auch Smart-TVs und IoT-Geräte, ohne Browser-Plugins. Sie betreiben Pi-hole als zentralen DNS-Server und stellen Router und Clients darauf um. Anfragen an bekannte Werbe-, Tracking- und Malware-Domains beantwortet Pi-hole dann mit einer leeren Adresse. Diese Anleitung zeigt die Einrichtung auf Debian 12 oder Ubuntu 24.04 mit Docker Compose: Port 53 gegenüber systemd-resolved freigeben, Persistenz, Web-Admin, Blocklisten, lokale DNS-Einträge, Update und Backup. Getestet mit dem Image pihole/pihole:2026.09.0 (Core 6.4.3, FTL 6.7.1).
Voraussetzungen
Pi-hole ist sehr sparsam und läuft auch auf einem Raspberry Pi. Eine GPU ist nicht nötig. Sie brauchen einen kleinen, dauerhaft laufenden Server im LAN.
- Server: Linux mit Docker und Docker Compose (Debian 12 oder Ubuntu 24.04). Weitere Software ist nicht nötig.
- RAM: 512 MB genügen. Im Test belegte der Container nach dem Start rund 20 MB.
- CPU: 1 Kern, x86-64 oder ARM (arm64, armv7).
- Speicher: 1 GB frei für Image und Daten, mehr nur für lange Query-Historien.
- Netzwerk: idealerweise eine feste IP-Adresse für den Server, denn Router und Clients zeigen später dauerhaft auf diese Adresse als DNS-Server.
- Optional: eine Domain mit Reverse-Proxy und HTTPS, falls Sie den Web-Admin von außen erreichen wollen.
Fehlt Docker noch, lesen Sie vorab unsere Grundlagen zu Docker Compose und Stacks.
Schritt 1: Port 53 freigeben (systemd-resolved)
Auf Ubuntu 24.04 (und Debian 12 mit aktiviertem systemd-resolved) belegt der lokale Stub-Resolver Port 53. Pi-hole scheitert dann mit address already in use. Prüfen Sie zuerst mit sudo ss -tulpn | grep ':53 ', ob der Port belegt ist. Wenn ja, deaktivieren Sie den Stub-Listener vor dem Container-Start per Drop-in-Datei:
sudo sh -c 'mkdir -p /etc/systemd/resolved.conf.d && printf "[Resolve]\nDNSStubListener=no\n" | tee /etc/systemd/resolved.conf.d/no-stub.conf'Damit der Host selbst weiter Namen auflöst, verlinken Sie /etc/resolv.conf auf die von resolved erzeugte Datei und starten den Dienst neu:
sudo sh -c 'rm -f /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'
sudo systemctl restart systemd-resolvedsudo ss -tulpn | grep ':53'Verifizieren: Der Befehl oben gibt keine Zeile mit Port 53 mehr aus, und getent hosts debian.org liefert auf dem Host weiterhin eine IP-Adresse.
Schritt 2: Verzeichnis und compose.yaml anlegen
Legen Sie ein Projektverzeichnis an. Das Volume legt Docker relativ zu diesem Ordner an:
mkdir -p /opt/pihole
cd /opt/piholeDie folgende compose.yaml entspricht der offiziellen Vorlage. Passen Sie Passwort und Zeitzone an:
services:
pihole:
container_name: pihole
image: pihole/pihole:latest # alternativ fixes Tag, z. B. pihole/pihole:2026.09.0
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
- "443:443/tcp" # optional, HTTPS Web-UI
environment:
TZ: 'Europe/Berlin'
FTLCONF_webserver_api_password: 'BITTE-AENDERN'
FTLCONF_dns_listeningMode: 'ALL'
volumes:
- './etc-pihole:/etc/pihole'
cap_add:
- NET_ADMIN
- SYS_TIME
- SYS_NICE
restart: unless-stoppedDie wichtigsten Punkte:
- image:
pihole/pihole:latestzieht die neueste Stable-Version. Für reproduzierbare Updates schreiben Sie ein datumsbasiertes Tag fest, etwapihole/pihole:2026.09.0(Stand September 2026).nightlyist der Entwicklungszweig. - ports:
53/tcpund53/udpsind für DNS zwingend,80für den Web-Admin.443ist optional für die HTTPS-Web-UI. Belegt bereits ein Reverse-Proxy Port 80/443, mappen Sie den Web-Admin auf einen freien Port, etwa"8080:80/tcp". Für DHCP oder NTP über Pi-hole ergänzen Sie67:67/udpbzw.123:123/udp. - volumes:
./etc-pihole:/etc/piholeenthält Konfiguration, Datenbanken und Adlists. Ohne dieses Volume gehen sie bei jeder Neuerstellung verloren. Das früher übliche./etc-dnsmasq.dist in Pi-hole v6 nicht mehr nötig. - FTLCONF_webserver_api_password: setzt das Admin-Passwort (Pi-hole v6). Ohne die Variable vergibt FTL ein zufälliges Passwort und schreibt es ins Log. Solange die Variable gesetzt ist, lässt sich das Passwort nur über sie ändern.
- FTLCONF_dns_listeningMode: 'ALL': im Docker-Default-Bridge-Netz zwingend, sonst beantwortet Pi-hole Anfragen Ihrer Clients nicht, weil sie aus Sicht des Containers aus einem fremden Subnetz kommen.
- cap_add:
NET_ADMIN(nur für den DHCP-Server),SYS_TIME(nur, wenn Pi-hole als NTP-Client die Host-Uhr stellen soll) undSYS_NICE(CPU-Priorität). Nicht benötigte Capabilities können Sie weglassen.--privilegedist nicht nötig.
Verifizieren: docker compose config -q im Projektordner gibt keine Fehlermeldung aus.
Schritt 3: Container starten und Passwort prüfen
Starten Sie den Stack im Hintergrund:
docker compose up -dBeim ersten Start legt Pi-hole die Datenbanken an und lädt die Standard-Blockliste (StevenBlack-Hosts). Den Fortschritt zeigen die Logs:
docker compose logs -f pihole
docker compose psHaben Sie FTLCONF_webserver_api_password nicht gesetzt, steht das zufällige Passwort im Log. Sie ändern es dann ohne Neuerstellung des Containers:
docker exec -it pihole pihole setpassword 'NEUES-PASSWORT'Ist die Variable gesetzt, bricht dieser Befehl mit webserver.api.password set by environment variable ab. Ändern Sie dann den Wert in der compose.yaml und führen Sie docker compose up -d aus.
Verifizieren: docker compose ps zeigt Up (healthy) nach etwa einer Minute. docker exec pihole pihole version gibt die Versionen von Core, Web und FTL aus.
Schritt 4: Web-Admin aufrufen und einrichten
Rufen Sie den Web-Admin unter http://SERVER-IP/admin auf, mit Port 443 alternativ unter https://SERVER-IP/admin (selbstsigniertes Zertifikat). Melden Sie sich mit dem Passwort aus FTLCONF_webserver_api_password an.
Das Dashboard zeigt DNS-Anfragen, Anteil geblockter Domains und die aktivsten Clients. Solange keine Clients auf Pi-hole zeigen, bleibt es leer, das ändert sich in Schritt 6. Wichtige Bereiche:
- Settings -> DNS: hier legen Sie die Upstream-Resolver fest (z. B. Quad9, Cloudflare oder ein eigener Resolver).
- Lists: Verwaltung der Blocklisten (Adlists).
- Settings -> Local DNS Records / Local CNAME Records: eigene Namen im LAN auflösen.
- Query Log: live nachvollziehen, welche Domains angefragt und geblockt werden.
Verifizieren: curl -sI http://SERVER-IP/admin/ liefert 302 Found mit Location: /admin/login, die Anmeldung im Browser öffnet das Dashboard.
Schritt 5: Blocklisten und lokale DNS-Einträge pflegen
Pi-hole bringt von Haus aus die StevenBlack-Hosts-Liste mit. Weitere Listen fügen Sie im Web-Admin unter Lists hinzu: Adlist-URL eintragen, speichern und anschließend die Gravity-Datenbank neu aufbauen. Das geht per Button Update Gravity in der UI oder auf der Kommandozeile:
docker exec -it pihole pihole -gDie Listen aktualisiert ein Cron-Job im Container wöchentlich. Manuell ist der Lauf nur nach dem Hinzufügen einer Liste nötig. Wenige gepflegte Listen verursachen weniger Fehlblockaden (false positives) als viele.
Mit lokalen DNS-Einträgen lösen Sie eigene Hostnamen im LAN auf. In Pi-hole v6 finden Sie das unter Settings -> Local DNS Records (A-Records, z. B. nas.heimnetz.lan auf eine interne IP) und Local CNAME Records (Aliase auf bestehende Namen).
Verifizieren: docker exec pihole pihole -g endet mit [✓] Done., und ein angelegter lokaler Eintrag wird per nslookup nas.heimnetz.lan SERVER-IP mit der hinterlegten IP beantwortet.
Schritt 6: Router und Clients auf Pi-hole zeigen
Ohne diesen Schritt blockiert Pi-hole nichts: Ihre Geräte müssen Pi-hole als DNS-Server nutzen. Am einfachsten verteilen Sie die Pi-hole-IP zentral über den Router.
- Empfohlen, über den Router: Tragen Sie im DHCP-Bereich des Routers die Pi-hole-IP als lokalen DNS-Server ein. Alle Clients beziehen die Adresse dann automatisch. Bei manchen Routern (z. B. FRITZ!Box) hinterlegen Sie den DNS-Server in den Internet- bzw. DNS-Einstellungen.
- Alternativ pro Gerät: Setzen Sie auf einzelnen Clients die Pi-hole-IP als bevorzugten DNS-Server.
Tragen Sie nur die Pi-hole-IP ein. Ein zweiter, öffentlicher DNS-Server als Fallback wird von Clients mitbenutzt und umgeht Pi-hole. Geräte mit fest eingetragenem DNS und Browser mit DNS-over-HTTPS (DoH) umgehen Pi-hole ebenfalls. Funktionstest von einem Client aus:
nslookup doubleclick.net SERVER-IPVerifizieren: Für die geblockte Domain antwortet Pi-hole mit 0.0.0.0, nslookup example.com SERVER-IP liefert echte Adressen, und im Query Log erscheint der Client.
Schritt 7: Reverse-Proxy und HTTPS (Sicherheit)
Der Web-Admin gehört nicht ungeschützt ins Internet, und Pi-hole darf kein offener Resolver sein. Betreiben Sie Pi-hole nur im LAN. Soll der Web-Admin extern erreichbar sein, stellen Sie einen Reverse-Proxy mit TLS und Authentifizierung davor. Port 53 geben Sie nie nach außen frei.
Traefik mit automatischem Let's-Encrypt-Zertifikat beschreibt unsere Anleitung Traefik als Docker-Reverse-Proxy mit HTTPS einrichten. Für reinen Fernzugriff ist ein VPN meist einfacher und sicherer, siehe WireGuard-VPN für Homeoffice und Standortanbindung einrichten. Der Web-Admin bleibt dann im internen Netz.
Verifizieren: Von einem Gerät außerhalb Ihres Netzes (z. B. Smartphone im Mobilfunk) beantwortet nslookup example.com IHRE-ÖFFENTLICHE-IP keine Anfrage, und der Web-Admin ist nur über VPN oder Proxy mit Anmeldung erreichbar.
Schritt 8: Update-Workflow
Für ein Update ziehen Sie das neue Image und erstellen den Container neu. Die Konfiguration im Volume ./etc-pihole bleibt erhalten:
docker compose pull && docker compose up -d
docker image prune -f # optional, alte Images aufraeumenVerzichten Sie bei Pi-hole auf automatische Updates per Watchtower. Aktualisieren Sie kontrolliert mit festem Tag und lesen Sie vorher die Release Notes.
Verifizieren: docker exec pihole pihole version zeigt die neuen Versionen, docker compose ps meldet Up (healthy).
Schritt 9: Backup
Der gesamte Zustand von Pi-hole – Konfiguration, Adlists und die Query-Datenbank – steckt im Volume ./etc-pihole. Für ein konsistentes Backup stoppen Sie den Container kurz, packen das Verzeichnis und starten wieder:
docker compose down && tar czf pihole-backup-$(date +%F).tar.gz ./etc-pihole && docker compose up -dAlternativ nutzen Sie den eingebauten Teleporter im Web-Admin unter Settings -> Teleporter -> Export. Er erzeugt ein Archiv mit allen Einstellungen, das Sie auf einer neuen Pi-hole-Instanz einspielen. Sichern Sie die Backups auf ein externes Ziel.
Verifizieren: tar tzf pihole-backup-*.tar.gz | head listet etc-pihole/pihole.toml und etc-pihole/gravity.db. Gehören Dateien im Volume nicht Ihrem Benutzer, führen Sie tar mit sudo aus.
Troubleshooting
- Container startet nicht,
address already in useauf Port 53:systemd-resolvedbelegt noch Port 53. Setzen SieDNSStubListener=no(Schritt 1) und startesystemd-resolvedneu. Mitsudo ss -tulpn | grep ':53'prüfen, dass der Port frei ist. - Host kann nach Schritt 1 keine Namen mehr auflösen: Der Symlink für
resolv.conffehlt. Setzen Sie ihn auf/run/systemd/resolve/resolv.confund startesystemd-resolvedneu. - Clients werden ignoriert:
FTLCONF_dns_listeningModeaufALLsetzen. - Passwort unbekannt: Wurde kein
FTLCONF_webserver_api_passwordgesetzt, steht das zufällige Passwort indocker logs pihole. Neu setzen mitdocker exec -it pihole pihole setpassword 'NEUES-PASSWORT'. Meldet der Befehlset by environment variable, ändern Sie den Wert in dercompose.yaml. - Es wird nichts geblockt: Clients nutzen einen anderen DNS-Server oder DoH. Nur die Pi-hole-IP eintragen (Schritt 6).
- Alte Anleitung mit
WEBPASSWORD/ServerIP/DNS1: Das sind v5-Variablen. In Pi-hole v6 geltenFTLCONF_*, vor allemFTLCONF_webserver_api_password. - Permission-Fehler mit SELinux (Fedora/RHEL): Mount als
./etc-pihole:/etc/pihole:zangeben.
Häufige Fragen
Brauche ich eine GPU oder starke Hardware für Pi-hole?
Nein. Pi-hole braucht keine GPU, 512 MB RAM und 1 GB Speicher genügen, ein Raspberry Pi reicht.
Warum scheitert der Start mit „address already in use“?
Weil systemd-resolved Port 53 belegt. Die Lösung beschreibt Schritt 1.
Was ist der Unterschied zwischen FTLCONF_webserver_api_password und WEBPASSWORD?
WEBPASSWORD gilt nur für v5, in v6 gilt FTLCONF_webserver_api_password. Generische FTLCONF_<setting>-Variablen überschreiben die pihole.toml. Ohne Passwort-Variable vergibt FTL ein zufälliges Passwort.
Wie sichere ich Pi-hole, wenn ich von außen zugreifen will?
Über ein VPN wie WireGuard oder einen Reverse-Proxy mit TLS und Anmeldung, siehe Schritt 7. Port 53 bleibt im LAN.
Wie aktualisiere ich Pi-hole und meine Blocklisten?
Pi-hole aktualisieren Sie mit docker compose pull && docker compose up -d. Die Blocklisten aktualisiert Pi-hole wöchentlich selbst, manuell mit docker exec -it pihole pihole -g.
Was ist der Unterschied zu AdGuard Home?
AdGuard Home (adguard/adguardhome) ist eine ähnliche Alternative mit eingebautem DoH/DoT und Setup-Assistent. Pi-hole ist ausgereift, gut dokumentiert und deckt mit Adlists, lokalen DNS-/CNAME-Records und Teleporter den Bedarf kleiner Unternehmen ab.
Fazit
Mit Docker Compose richten Sie Pi-hole in rund einer halben Stunde als netzwerkweiten Werbe- und Tracker-Blocker ein. Entscheidend sind der freie Port 53, die FTLCONF_*-Variablen und das Volume ./etc-pihole. Sobald Router und Clients auf die Pi-hole-IP als DNS zeigen, filtert Pi-hole für jedes Gerät im Netz. Halten Sie die Blocklisten schlank, geben Sie den Dienst nicht ins Internet frei und sichern Sie vor Updates per Backup oder Teleporter-Export.
Weiterführende Anleitungen und Quellen
- Docker Compose Grundlagen: Stacks verstehen und betreiben
- Traefik als Docker-Reverse-Proxy mit HTTPS einrichten
- WireGuard-VPN für Homeoffice und Standortanbindung einrichten
- Weitere Anleitungen in der Kategorie Netzwerk
Quellen:


