X

How Pi-hole Broke DNS for My Other Docker Containers (And the Quick Fix)

I’ve used Pi-hole off and on in the past. I really like the idea of it, but it breaks stuff often enough that at times I’ve turned it back off. I recently added it back to my network as a Docker container just to manage local DNS (at the moment, ad blocking is disabled). That’ll be a separate post, but I wanted to implement a custom domain for all my containers (previously just using a bookmarked IP address / port to access them).

However, after pointing my router to Pi-hole for DNS, I realized DNS wasn’t working for any other Docker containers on the same host, but it was working fine for other devices on my network. For instance, my changedetection.io container was showing an error like this on every site it tried to check: Exception: Page.goto: net::ERR_NAME_NOT_RESOLVED at [URL] Call log: navigating to [URL], waiting until "load" A quick Google search revealed I’m not alone, and there are a few options for fixing the issue.

What happened?

Here’s what actually broke: Pi-hole, running as a container, grabbed port 53 (the DNS port) on my host’s network interface.

Docker’s own containers, by default, use an internal DNS proxy at 127.0.0.11. This proxy is supposed to forward requests out to whatever the host uses for DNS (as set in /etc/resolv.conf).

But, because both Pi-hole and my app containers are on a custom user-defined Docker network, Docker’s iptables rules would rewrite the source IP of the DNS reply. The container expects a reply from Pi-hole’s IP, but instead, it sees a reply from the bridge gateway IP, which it doesn’t trust. So, the response gets dropped, and DNS just fails—quietly, of course.

The Fix: Bind Pi-hole DNS to the Host’s IP

I wanted the solution that’s the most portable and the least fragile. I want all my config to live in the Docker compose files and not rely on custom host configurations I’d forget in the future. Since I know my Docker host has a static IP, all I had to do was bind Pi-hole’s DNS port to my host’s LAN IP instead of every interface.

So in my pihole.yml, I changed this:

ports:
- "53:53/udp"
- "53:53/tcp"

to this:

ports:
- "192.168.1.2:53:53/udp"
- "192.168.1.2:53:53/tcp"

(Obviously, swap out that IP for whatever your server actually uses.)

As soon as I made that switch and restarted Pi-hole, every container started resolving both local and internet domains again. Voila! 🥳

Alternate Solutions

There are a couple of other solid ways to tackle this if you want a slightly different approach:

Option 1: Use the Host’s Local Resolver for Docker
Perhaps the most popular method is to point your host’s DNS (the /etc/resolv.conf file) to Pi-hole running on 127.0.0.1. That way, Docker’s internal DNS proxy forwards container queries straight to Pi-hole, all on localhost. This approach is widely recommended since it doesn’t require editing each services Docker compose file.

Option 2: Set Docker’s Daemon DNS (/etc/docker/daemon.json)
Another approach is to configure Docker itself to always use Pi-hole for DNS lookups by editing /etc/docker/daemon.json:

{ "dns": ["192.168.1.2", "1.1.1.1"] }

(Once again, swap out the first IP for whatever your server actually uses.)

This absolutely works, but it’s one of those host-level changes you have to remember if you ever rebuild or move your server.

Option 3: Use a Shared Docker Network for Everything
Another well-recommended route is to create a user-defined bridge network and make every container – Pi-hole included – use that as their default network. I avoided this route because I already had the containers on a shared, custom network and it still wasn’t working, and because this required editing every Docker compose file.

Option 4: Run Pi-hole with network_mode: host
This sidesteps Docker’s bridge networking entirely and lets Pi-hole bind directly to all of the host’s network interfaces. It solves the DNS issues, but it also means you lose a lot of Docker’s isolation benefits, and it can create port conflicts—especially if you’re running a reverse proxy like Traefik or anything else that wants to use ports 80/443. For me, that was a non-starter.

The Takeaway

If you’re using Pi-hole in Docker as your DNS, and you notice containers suddenly can’t resolve anything, then you have a few options for a fix. Binding Pi-hole’s DNS port to your host’s LAN IP is a quick, clean fix—and it’ll survive host migrations since it lives right in your Compose file.

If you’ve run into this issue, leave a comment with which fix you choose and why!

Categories: Uncategorized
Related Post