Pi-hole mit Docker Compose betreiben
Pi-hole als Container statt als Systeminstallation: eine nachvollziehbare compose.yaml, der Umgang mit belegtem Port 80, ein Speicherlimit für kleine Geräte und die Frage, welchen Upstream-DNS du eintragen solltest.
Von Niclas Hennrich · Veröffentlicht: · 4 Min. Lesezeit
Kurz gesagt: Lege ein Verzeichnis wie /opt/pihole an, schreib eine
compose.yaml mit Port 53 für DNS, einem freien Host-Port für die
Weboberfläche und einem Volume für /etc/pihole, starte mit
docker compose up -d und trage die IP des Hosts anschließend als DNS-Server
im Router ein. Kritisch sind nur zwei Dinge: Port 53 muss frei sein, und der
Upstream-DNS ist eine bewusste Entscheidung.
Pi-hole filtert Werbung und Tracker für das ganze Netz, indem es als DNS-Server arbeitet und Anfragen an bekannte Werbedomains ins Leere laufen lässt. Es läuft auf jedem kleinen Dauerläufer — einem Raspberry Pi, einem Mini-PC, einem NAS.
Dieser Guide beschreibt die Container-Variante. Sie lohnt vor allem dann, wenn auf dem Gerät noch etwas anderes läuft: Das gesamte Setup steht in einer Datei, die du versionieren und auf einem anderen Host identisch wieder hochziehen kannst.
Voraussetzungen und der Port-53-Check #
Nötig sind Docker samt Compose-Plugin sowie ein Host mit fester IP-Adresse — ein DNS-Server, dessen Adresse sich ändert, fällt für das ganze Netz aus. Vergib die Adresse am besten als feste Zuordnung im Router, nicht statisch auf dem Gerät.
Vor dem Start die wichtigste Prüfung: Ist Port 53 frei?
sudo ss -tulpn | grep ':53'Kommt keine Ausgabe, ist alles gut. Erscheint systemd-resolved, belegt der
lokale DNS-Stub den Port. Dann deaktivierst du diesen Stub:
sudo mkdir -p /etc/systemd/resolved.conf.d
printf '[Resolve]\nDNSStubListener=no\n' | \
sudo tee /etc/systemd/resolved.conf.d/10-no-stub.conf
sudo systemctl restart systemd-resolvedDanach ist Port 53 frei für Pi-hole.
Die compose.yaml #
Lege ein Verzeichnis an und erstelle darin die Compose-Datei:
sudo mkdir -p /opt/pihole/etc-pihole
cd /opt/pihole
sudo nano compose.yamlservices:
pihole:
image: pihole/pihole:latest
container_name: pihole
restart: unless-stopped
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80/tcp"
# Auf Geräten mit wenig RAM (z. B. Pi 3B+ mit 1 GB) sinnvoll
mem_limit: 256m
volumes:
- /opt/pihole/etc-pihole:/etc/pihole
environment:
TZ: "Europe/Berlin"
FTLCONF_webserver_api_PASSWORD: "<PASSWORT>"
# Upstream-DNS — bewusste Entscheidung, siehe unten
FTLCONF_dns_upstreams: "<ROUTER-IP>"Drei Stellen verdienen einen zweiten Blick:
Das Port-Mapping 8080:80 legt die Weboberfläche auf Host-Port 8080.
Das ist der einfachste Weg, Pi-hole neben einem bereits laufenden Webserver
zu betreiben — hier stammt die Wahl daraus, dass Port 80 auf dem Gerät schon
von einem nginx belegt war. Ist bei dir Port 80 frei, kannst du auch
80:80 schreiben. Die DNS-Ports bleiben in jedem Fall auf 53.
Das Speicherlimit ist optional, auf kleinen Geräten aber hilfreich: Es verhindert, dass ein einzelner Container im Fehlerfall den gesamten Arbeitsspeicher belegt. 256 MB reichen für Pi-hole im Heimnetz.
Das Volume bindet /opt/pihole/etc-pihole in den Container. Dort liegen
Blocklisten, Einstellungen und Statistiken — also alles, was ein Update
überleben soll. Dieses Verzeichnis gehört ins Backup; in ein Git-Repository
gehört es dagegen nicht, weil es Laufzeitdaten und die Query-Datenbank
enthält.
Starten:
sudo docker compose up -d
sudo docker compose logs -f piholeDie Weboberfläche erreichst du danach unter
http://<HOST-IP>:8080/admin.
Die eigentliche Entscheidung: Welcher Upstream? #
Pi-hole beantwortet keine DNS-Anfragen selbst, sondern entscheidet nur, ob eine Domain blockiert wird. Alles andere reicht es an einen Upstream-DNS weiter — und dessen Wahl bestimmt, wer die Anfragen deines Netzes am Ende sieht.
Router als Upstream (im Beispiel oben): Lokale Gerätenamen, die dein Router kennt, bleiben auflösbar — praktisch, wenn du Geräte im Heimnetz unter Namen ansprichst. Der Preis: Router und Provider sehen weiterhin jede Anfrage. Für den Einstieg ist das der bequemste Weg, und genau so lief dieses Setup zunächst.
Eigener rekursiver Resolver (etwa Unbound): Dein Netz fragt die DNS-Hierarchie selbst ab, statt einem Dritten zu vertrauen. Dafür brauchst du eigene Einträge für lokale Namen — sonst laufen interne Hostnamen ins Leere oder, schlimmer, nach außen. Wie das sauber zusammenspielt, steht im Guide Pi-hole mit Unbound einrichten.
Die Reihenfolge, die sich bewährt: erst mit dem Router als Upstream starten und prüfen, ob das Blocken im Alltag funktioniert — dann auf einen eigenen Resolver umstellen, wenn du die Namensauflösung im Griff hast.
Pi-hole im Netz aktivieren #
Damit das Netz den Filter auch nutzt, muss der Router Pi-hole als DNS-Server verteilen. Trage die IP des Docker-Hosts als DNS-Server in den DHCP-Einstellungen deines Routers ein.
Ein Detail, das gern Zeit kostet: Viele Router verteilen den DNS-Server nur beim Erneuern der DHCP-Lease. Geräte, die schon eine Adresse haben, nutzen noch den alten Eintrag. Ein Neustart der Geräte oder das Ablaufen der Lease sorgt für Klarheit. Ob es funktioniert, siehst du im Pi-hole-Dashboard: Dort tauchen die anfragenden Clients einzeln auf.
Updates und Rückbau #
Ein Update ist ein Image-Wechsel:
cd /opt/pihole
sudo docker compose pull
sudo docker compose up -dWeil die Konfiguration im Volume liegt, bleiben Blocklisten und Einstellungen erhalten. Und falls Pi-hole doch nicht das Richtige ist:
sudo docker compose downDanach im Router den DNS-Eintrag zurücksetzen — das Netz löst wieder über den
Router auf, und auf dem System selbst bleibt nichts zurück außer dem
Verzeichnis unter /opt/pihole.
Wie es weitergeht #
Wenn Pi-hole läuft, sind die beiden nächsten sinnvollen Schritte: Unbound als rekursiver Upstream, damit die Auflösung nicht mehr über Router und Provider läuft, und — falls du noch schwankst, ob Pi-hole überhaupt die richtige Wahl ist — der Vergleich Pi-hole gegen AdGuard Home.
Häufige Fragen
- Warum Pi-hole als Container statt direkt installiert?
- Weil Konfiguration und Zustand sauber getrennt bleiben: Die compose.yaml beschreibt das gesamte Setup in einer versionierbaren Datei, ein Update ist ein Image-Wechsel, und ein Rückbau hinterlässt keine Spuren im System. Auf einem Gerät, das noch andere Dienste trägt, ist das der übersichtlichere Weg. Wer ausschließlich Pi-hole betreibt und keine Container nutzt, fährt mit der klassischen Installation genauso gut.
- Pi-hole startet nicht, weil Port 53 belegt ist. Was tun?
- Auf vielen Systemen hält systemd-resolved den Port 53 besetzt. Prüfen lässt sich das mit sudo ss -tulpn und der Suche nach Port 53. Die saubere Lösung ist, den DNSStubListener von systemd-resolved zu deaktivieren, damit der Port frei wird. Erst danach kann Pi-hole selbst auf 53 lauschen.
- Wie ändere ich den Web-Port, wenn Port 80 schon belegt ist?
- Im Port-Mapping der compose.yaml: Die Angabe 8080:80 bedeutet, dass der Container-Port 80 auf dem Host unter 8080 erreichbar ist. Die Weboberfläche liegt dann unter http://<HOST-IP>:8080/admin. Der DNS-Port 53 muss dagegen unverändert bleiben, weil Clients DNS-Anfragen immer an Port 53 schicken.
- Welchen Upstream-DNS soll ich in Pi-hole eintragen?
- Trägst du deinen Router ein, bleiben lokale Namen des Routers auflösbar — der Router und darüber der Provider sehen aber weiterhin alle Anfragen. Trägst du einen eigenen rekursiven Resolver wie Unbound ein, fragt dein Netz die DNS-Hierarchie selbst ab, und du brauchst für lokale Namen eigene Einträge. Beides ist legitim; die Entscheidung hängt davon ab, ob dir lokale Namensauflösung oder Unabhängigkeit wichtiger ist.
- Gehen meine Einstellungen bei einem Container-Update verloren?
- Nein, sofern das Verzeichnis mit der Pi-hole-Konfiguration als Volume eingebunden ist. Der Container ist dann austauschbar, während Blocklisten, Einstellungen und Statistiken auf dem Host liegen. Genau dieses Verzeichnis gehört auch in dein Backup — der Container selbst nicht, der wird bei Bedarf einfach neu erzeugt.
Weiterlesen
Netzwerk
Pi-hole mit Unbound: Werbefilter plus eigener rekursiver DNS
Warum Pi-hole allein deine DNS-Anfragen nur weiterreicht — und wie du mit Unbound als rekursivem Resolver unabhängig von Google, Cloudflare & Co. wirst. Mit kompletter Konfiguration.
Netzwerk
Pi-hole vs. AdGuard Home: Welcher DNS-Filter passt zu dir?
Beide blocken Werbung im ganzen Netz — aber mit unterschiedlicher Philosophie. Der ehrliche Vergleich: Funktionen, Verschlüsselung, Bedienung und eine klare Empfehlung.
Docker
Docker in Proxmox: VM oder LXC-Container?
Docker unter Proxmox läuft in einer VM oder im LXC — aber nur einer der beiden Wege ist offiziell empfohlen. Die Architektur erklärt, beide Wege konkret gezeigt, mit ehrlicher Entscheidungshilfe.