Pi-hole to Unbound forwarding fails

Hi @diginc and all. I can’t figure out why my Pi-hole forwarding to Unbound fails.

This is setup as two containers, both on Docker’s bridge network. Pi-hole is 192.168.1.13 (172.17.0.2) on port 53 tcp and udp, while Unbound is 192.168.1.13 (172.17.0.3) on port 50053 tcp and udp. Pi-hole’s Upstream DNS Server is set to 192.168.1.13#50053.

Unbound correctly resolves anything sent directly to port 50053. Pi-hole’s admin interface works perfectly. However, Pi-hole will not resolve anything sent to its port 53. In the log, it will say

18:37:20 dnsmasq[9821]: query[A] foo.com from 192.168.1.100
18:37:20 dnsmasq[9821]: forwarded foo.com to 192.168.1.13
18:37:22 dnsmasq[9821]: query[A] time1.google.com from 172.17.0.1
18:37:22 dnsmasq[9821]: forwarded time1.google.com to 192.168.1.13

However, the query never arrives to Unbound and doesn’t show in its logs.

I can ping between the two containers. I also tried disabling the Docker host’s iptables. And, as mentioned, I can successfully resolve using this Unbound instance from other devices on the network, e.g. from 192.168.1.100, I can dig @192.168.1.13 -p 50053 foo.com and receive an answer from Unbound, but I cannot dig @192.168.1.13 -p 53 foo.com (“connection timed out; no servers could be reached”).

I have this same setup running on my Synology without issue, but am trying to move off of that and onto an ESXi server on the same home network running Photon OS and Docker.

I uploaded a Pi-hole debug log: 7jms44n2up, but I’m doubtful this is a Pi-hole issue per se, unless I’ve somehow goofed the docker run. Here’s the command:

docker run --name pihole \
--volume=/docker/pihole/etc/pihole:/etc/pihole \
--cap-add=NET_ADMIN \
--dns=127.0.0.1 \
--dns=1.1.1.1 \
--network=bridge \
--publish=53:53/tcp \
--publish=53:53/udp \
--publish=80:80 \
--publish=443:443 \
--env IPv6=false \
--env ServerIP=192.168.1.13 \
--env VIRTUAL_HOST=pihole.mydomain.net \
--env TZ=America/New_York \
--env WEBPASSWORD=xxyyzz \
--env DNS1=192.168.1.13#50053 \
--env DNS2=no \
--log-driver=json-file \
--restart=unless-stopped \
--detach=true \
pihole/pihole:latest

Suggestions welcome, and thanks for reading!

That’s probably your problem, 2 containers on the default bridge network will often have trouble talking to each other since they lock it down a bit more than a user created bridge network. I’d suggest creating your own network with bridge mode or using docker-compose which will do that for you automatically.

The default bridge network is considered a legacy detail of Docker and is not recommended for production use. Configuring it is a manual operation, and it has technical shortcomings.

… Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy. On a user-defined bridge network, containers can resolve each other by name or alias.

It says they should be able to communicate if you used IP addresses…however even if you’re using IPs I’d recommend not using the default bridge network for multi-container stacks. Give a different bridge network a try (docker network create mynetwork) and see if that works better for you

Thanks for responding to the op. I was banging my head on this same issue all weekend and thanks to your post I was able to get it working. Here’s an excerpt from my CloudFormation template:

 Metadata:
      AWS::CloudFormation::Init:
        configSets:
          myCfnConfigSet:
            - "start_containers"
        start_containers:
          commands:
            01_create_bridge:
              command: "docker network create -d bridge --subnet 10.0.0.0/24 dns"
            02_run_unbound:
              command: "docker run -d --ulimit nofile=10000:10000 --network=dns --ip=10.0.0.5 --name unbound  --cap-add=NET_ADMIN -e TZ=America/New_york klutchell/unbound"
            03_run_pihole:
              command: !Sub "docker run -d --network=dns --ip=10.0.0.10 --name pihole -p 53:53/tcp -p 53:53/udp -p 80:80 -e DNS1=10.0.0.5 -e DNS2=no -e TZ=America/New_York -e ServerIP=${myEIP} -e VIRTUAL_HOST=${myDNSRecord} -e WEBPASSWORD=${PiHolePassword} -e DNSMASQ_LISTENING=local --restart=unless-stopped --cap-add=NET_ADMIN --dns=127.0.0.1 --dns=1.1.1.1 -v /mnt/dockershare/pihole:/etc/pihole -v /mnt/dockershare/dnsmasq.d:/etc/dnsmasq.d pihole/pihole"

I haven’t merged the code into my repo yet but I should have time this weekend.

I’m super late here, but thank you @diginc for pointing out the issues with the legacy bridge network.

For anyone else that may run into a similar networking issue: I’ve placed unbound and pihole in a user-defined network named “dns-net”. I had to change the docker run DNS1 parameter from the host machine’s IP (“192.168.1.13#50053” in my post above) to my Unbound container’s docker IP (“172.19.0.2”). This can be done with docker inspect to avoid hard-coding Unbound’s container IP (see below).

Here are the run commands in case they might help anyone else:

docker run --name=unbound --hostname=unbound \
--volume=/home/rancher/docker/unbound:/opt/unbound/etc/unbound/ \
--network=dns-net \
--publish=5354:53/tcp \
--publish=5354:53/udp \
--log-driver=json-file \
--restart=unless-stopped \
--detach=true \
mvance/unbound:latest


docker run --name=pihole --hostname=pihole \
--volume=/home/rancher/docker/pihole:/etc/pihole/ \
--network=dns-net \
--publish=53:53/tcp \
--publish=53:53/udp \
--publish=67:67 \
--publish=50314:80 \
--publish=50315:443 \
--dns=127.0.0.1 \
--dns=1.1.1.1 \
--env ServerIP=192.168.1.14 \
--env VIRTUAL_HOST=pihole.mydomain.net \
--env TZ=America/New_York \
--env WEBPASSWORD=admin12345 \
--env DNS1=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 'unbound') \
--env DNS2=no \
--log-driver=json-file \
--restart=unless-stopped \
--detach=true \
pihole/pihole:latest

better late than never, how can I accomplish the same using docker-compose?