Docker breaks the host network, or containers cannot resolve names
Docker's default bridge subnet collides with the real network, or the container's DNS is pointing somewhere it cannot reach.
What you see
After installing Docker, part of the corporate network becomes unreachable from the host. Or containers can reach IP addresses but not resolve names.
What is actually wrong
Docker allocates 172.17.0.0/16 by default, which is a real routed range on plenty of networks. Container DNS defaults to the host's resolver, which on systemd systems is 127.0.0.53 — an address that means nothing inside a container's network namespace.
Codes and articles
Fixes (2)
Move Docker off the conflicting range
A subnet collision. Confirm it first — the symptom is specific.
Compare Docker's networks against the real routing table.
docker network lsdocker network inspect bridge --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}'ip route show
A route to 172.17.0.0/16 via docker0 will beat a route to the same range via the real gateway. Everything in that range becomes unreachable, and nothing in the error mentions Docker.
Set both the default bridge and the pool used for user-defined networks.
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'{ "bip": "10.200.0.1/24", "default-address-pools": [ {"base": "10.201.0.0/16", "size": 24} ]}EOF
Setting bip alone only moves the default bridge. Compose creates its own networks from the address pool, so without the second setting the conflict returns the first time someone runs docker compose up.
Restart Docker and remove the old networks so they are recreated in the new range.
sudo systemctl restart dockerdocker network prune -f
Confirm the routes are now out of the way.
ip route show | grep -E 'docker|br-'
ip route show | grep dockerdocker run --rm alpine ping -c2 1.1.1.1
Give containers a resolver they can reach
Containers resolve nothing, or only external names.
See what the container was given.
docker run --rm alpine cat /etc/resolv.confcat /etc/resolv.conf
If the host's resolv.conf points at 127.0.0.53, Docker substitutes public resolvers — which cannot resolve internal names.
resolvectl status | head -20This is why a container can reach the internet and not the company's own DNS. The loopback stub resolver is meaningless inside the container's namespace, so Docker silently swaps in 8.8.8.8.
Set real resolvers for the daemon.
sudo tee -a /etc/docker/daemon.json >/dev/null <<'EOF'{ "dns": ["10.0.0.10", "10.0.0.11"], "dns-search": ["example.local"]}EOFsudo systemctl restart docker
Remember that container-to-container name resolution only works on a user-defined network, not on the default bridge.
docker network create appnetdocker run -d --name db --network appnet postgres:16docker run --rm --network appnet alpine nslookup db
This surprises people constantly: containers on the default bridge cannot resolve each other by name at all. Creating a network is the fix, and it takes one command.
Check the daemon.json is valid JSON — two separate objects appended will stop Docker starting.
python3 -m json.tool < /etc/docker/daemon.json
docker run --rm alpine sh -c 'nslookup fileserver.example.local; nslookup google.com'Related faults
Where this stops. This write-up was written and checked by hand. It says what each step changes, how to confirm it worked and how to reverse it, and anything destructive is flagged before you reach it. If it does not match what your machine is doing, search the Support Centre for the exact code or message — and when something needs a person, get in touch.