Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Server & Netzwerk 02.06.2026 · 10 min Lesezeit Geprüft 19.10.2026

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.10.0.

Werbung Mit * 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

Titelbild: Pi-hole mit Docker einrichten, DNS, Filter, Netzwerk

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.

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-resolved
sudo ss -tulpn | grep ':53'

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/pihole

Die 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.10.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-stopped

Die wichtigsten Punkte:

  1. image: pihole/pihole:latest zieht die neueste Stable-Version. Für reproduzierbare Updates schreiben Sie ein datumsbasiertes Tag fest, etwa pihole/pihole:2026.10.0 (Stand Oktober 2026). nightly ist der Entwicklungszweig.
  2. ports: 53/tcp und 53/udp sind für DNS zwingend, 80 für den Web-Admin. 443 ist 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 Sie 67:67/udp bzw. 123:123/udp.
  3. volumes: ./etc-pihole:/etc/pihole enthält Konfiguration, Datenbanken und Adlists. Ohne dieses Volume gehen sie bei jeder Neuerstellung verloren. Das früher übliche ./etc-dnsmasq.d ist in Pi-hole v6 nicht mehr nötig.
  4. 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.
  5. 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.
  6. cap_add: NET_ADMIN (nur für den DHCP-Server), SYS_TIME (nur, wenn Pi-hole als NTP-Client die Host-Uhr stellen soll) und SYS_NICE (CPU-Priorität). Nicht benötigte Capabilities können Sie weglassen. --privileged ist nicht nötig.

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 -d

Beim 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 ps

Haben 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.

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:

  1. Settings -> DNS: hier legen Sie die Upstream-Resolver fest (z. B. Quad9, Cloudflare oder ein eigener Resolver).
  2. Lists: Verwaltung der Blocklisten (Adlists).
  3. Settings -> Local DNS Records / Local CNAME Records: eigene Namen im LAN auflösen.
  4. Query Log: live nachvollziehen, welche Domains angefragt und geblockt werden.

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 -g

Die 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).

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.

  1. 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.
  2. 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-IP

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.

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 aufraeumen

Verzichten Sie bei Pi-hole auf automatische Updates per Watchtower. Aktualisieren Sie kontrolliert mit festem Tag und lesen Sie vorher die Release Notes. Im Test mit dem Update von 2026.09.0 auf 2026.10.0 (Core 6.5, Web 6.6.1, FTL 6.8) blieben Passwort und ein eigener Sperreintrag erhalten, gesperrte Domains wurden weiter mit 0.0.0.0 beantwortet, ein falsches Passwort lehnte die API mit 401 ab, pihole -g lief durch, und der Container war wieder healthy. Das Release behebt laut Release Notes 17 Sicherheitslücken in FTL, Web und Core, darunter mehrere mit hoher Einstufung; spielen Sie es zeitnah ein.

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 -d

Alternativ 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.

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 use auf Port 53: systemd-resolved belegt noch Port 53. Setzen Sie DNSStubListener=no (Schritt 1) und starte systemd-resolved neu. Mit sudo 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.conf fehlt. Setzen Sie ihn auf /run/systemd/resolve/resolv.conf und starte systemd-resolved neu.

Clients werden ignoriert

FTLCONF_dns_listeningMode auf ALL setzen.

Passwort unbekannt

Wurde kein FTLCONF_webserver_api_password gesetzt, steht das zufällige Passwort in docker logs pihole. Neu setzen mit docker exec -it pihole pihole setpassword 'NEUES-PASSWORT'. Meldet der Befehl set by environment variable, ändern Sie den Wert in der compose.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 gelten FTLCONF_*, vor allem FTLCONF_webserver_api_password.

Permission-Fehler mit SELinux (Fedora/RHEL)

Mount als ./etc-pihole:/etc/pihole:z angeben.

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

  1. Docker-Container automatisch aktualisieren
  2. Docker und Docker Compose auf Linux installieren
  3. Docker Compose Grundlagen: Stacks verstehen und betreiben
  4. Traefik als Docker-Reverse-Proxy mit HTTPS einrichten
  5. WireGuard-VPN für Homeoffice und Standortanbindung einrichten
  6. Weitere Anleitungen in der Kategorie Netzwerk

Quellen:

  1. Pi-hole, Offizielle Docker-Doku (compose-Beispiel, ENV-Variablen, Setup)
  2. Pi-hole, Docker Tips and Tricks (systemd-resolved / Port 53)
  3. GitHub: pi-hole/docker-pi-hole (README, Image-Tags)
  4. GitHub Releases (aktuelle Tags, z. B. 2026.05.0)