What Pi-hole actually does

Pi-hole isn’t a browser ad blocker: it’s a DNS resolver. Every device on your network that points to it as its DNS server runs each query through gravity, the compiled list of ad and tracking domains. If the domain is on the list, Pi-hole answers with 0.0.0.0 instead of forwarding the question to the internet; if it isn’t, it forwards it to a real resolver (in this lab, 1.1.1.1 and 8.8.8.8) and hands you back the genuine answer. That’s why blocking works the same in a browser, a phone app, or a smart TV’s firmware: it doesn’t depend on an extension installed per device.

Why the container needs the FTLCONF_* variables

Version 6 replaced environment variables like WEBPASSWORD with the FTLCONF_ prefix, which maps directly onto FTL’s own configuration keys. In this lab we set the panel password with FTLCONF_webserver_api_password, open the DNS listener to every interface with FTLCONF_dns_listeningMode=ALL, and, something people often forget, declare the upstream resolvers with FTLCONF_dns_upstreams: without that variable Pi-hole won’t forward anything at all.

Pairs well with the rest of your self-hosted stack

We already covered how to install Pi-hole with Docker step by step, and if you want an alternative with built-in DNS-over-HTTPS, check out how to install AdGuard Home with Docker. You’ll find more self-hosted infrastructure pieces in the Tools category and the rest of our fully verified, step-by-step guides in the hands-on labs.

Official references

For the full breakdown of every environment variable, see the official docker-pi-hole repository, for the exact behavior of NULL blocking mode see the FTLDNS documentation, and for the published image versions see the Docker Hub repository.

FAQ

What is Pi-hole and how does it block ads at the DNS level?

Pi-hole is a DNS resolver that acts as a sinkhole: it checks every query against its blocklists (gravity) and, on a match, answers it itself instead of forwarding it to the internet. The device never actually reaches the ad server, so the ad never loads, in any app or device using that DNS.

Why does a blocked domain resolve to 0.0.0.0 instead of failing?

0.0.0.0 is Pi-hole's default blocking mode, called NULL: it's an address no real service uses, so the browser or app's request fails instantly instead of hanging until a timeout expires. It's a fast, predictable answer, not a network error.

Do you need to change the router's DNS to block ads on every device?

For a genuinely network-wide block, yes: you point the router's DNS at the Pi-hole container's IP and every device that connects inherits it automatically over DHCP. In this lab we publish port 53 and query it directly with dig, since the container doesn't have a real router network to point at.

Can I see the query log without opening the web panel?

Yes: Pi-hole v6 stores every query in a SQLite database (pihole-FTL.db) that you can read with pihole-FTL sqlite3 from the command line, including each query's status (blocked, forwarded, or served from cache). The web panel just visualizes that same data.