Debugging DNS Issues in Docker Networks
AI generated
FROM
RUN
Docker · Networking · DNS · Debugging
Debugging DNS Issues in Docker Networks
from symptom to root cause in a few steps

Name resolution failure is one of the most common and, at the same time, one of the least understood errors in Docker setups. Anyone who knows how the embedded DNS server works and which tools expose the root cause can find DNS issues in Docker networks in minutes instead of hours.

17 min read DNS · resolv.conf · nslookup · dig Docker Engine 24+ · Compose v2

1. How DNS resolution works in Docker networks

Before you can debug DNS issues in Docker networks, you need clarity on how name resolution actually happens there. In a custom bridge, overlay or macvlan network, Docker automatically writes an /etc/resolv.conf at container start time that points to an internal DNS server. Requests for container names or, in Compose, service names, are answered directly there, all other requests are forwarded to the configured upstream DNS servers, usually inherited from the Docker host.

This means DNS in a Docker network is a two-stage system. First, the embedded resolver checks whether the requested name is a known container or service, only then does the request go outward. Most DNS issues in Docker networks arise exactly at this boundary, either because the container is not attached to the right network to benefit from the first stage, or because the second stage, the external DNS servers, is misconfigured or unreachable.

2. The embedded DNS server 127.0.0.11

Every container in a custom network gets the address 127.0.0.11 written into its /etc/resolv.conf as the DNS server. This address is not a real network service outside the container but is intercepted inside the container's namespace by an iptables rule from the Docker daemon and answered internally. Anyone investigating DNS issues in Docker networks should check exactly this file first, because a missing or wrong 127.0.0.11 line usually points to a fundamental networking problem.

Important to understand: the embedded DNS server only knows containers and services in the same custom network. A container trying to resolve the name of a container in a completely different network gets no answer, even if both containers run on the same host. This network boundary is one of the most common causes of DNS issues in Docker networks that look like a DNS failure at first glance but are actually a network segmentation problem.


# Inspect the resolv.conf inside a running container
docker exec my-app cat /etc/resolv.conf

# Expected output in a custom network:
# nameserver 127.0.0.11
# options ndots:0

# Check which network a container actually belongs to
docker inspect my-app --format '{{range $net, $conf := .NetworkSettings.Networks}}{{$net}} {{end}}'

3. Typical symptoms of a DNS problem

The classic symptom of DNS issues in a Docker network is an error message like Name or service not known or Could not resolve host, triggered by the application itself, often right at startup when it tries to connect to the database or another service. A second, more subtle symptom is not a hard error at all but a noticeable delay of several seconds before every connection, caused by DNS timeouts running in the background before a fallback kicks in.

A third pattern often shows up after a docker compose restart: the application worked before the restart, then name resolution suddenly fails afterward even though nothing changed in the configuration. This almost always points to cached DNS answers inside the application itself, not to an actual DNS issue in the Docker network, because Docker itself updates its internal DNS entries immediately on every container restart.

4. Using diagnostic tools inside the container

For systematic diagnosis of DNS issues in Docker networks, you need tools inside the container, not just on the host, because name resolution happens in the container's namespace. nslookup and dig are the standard tools but are often not preinstalled in minimal images like Alpine or Distroless and have to be installed afterward or provided through a debug image. getent hosts, on the other hand, uses the standard C library for name resolution and is already available in practically every Linux image.

An often overlooked diagnostic step: docker network inspect on the host shows which containers are actually registered in a network and under what name. If the expected service name does not match the actually registered name, for example due to a typo in the Compose file, that immediately explains many seemingly mysterious DNS issues in Docker networks, with no deeper DNS analysis needed.


# Resolve a name using getent, available in almost every image
docker exec my-app getent hosts shop-db

# If dig is available, inspect the full DNS response
docker exec my-app dig shop-db +short

# List all containers actually registered in a network
docker network inspect shop-network \
  --format '{{range .Containers}}{{.Name}} {{end}}'

# Quick one-off debug container with full networking tools
docker run --rm --network shop-network nicolaka/netshoot \
  dig shop-db

5. Root cause one: containers in the default bridge network

By far the most common cause of DNS issues in Docker networks is a container still running in the default bridge network because no --network parameter was given at docker run time. The default bridge runs no embedded DNS server for container names, containers have to reach each other via fixed IP addresses there. Anyone using a service name out of habit, the way it works in Compose setups, reliably gets a name resolution error in the default bridge.

The fix is simple but easy to overlook: create a custom network and assign both containers to it. In Compose projects this DNS issue in the Docker network occurs less often, because Compose automatically creates a project network, but it can still arise when a service explicitly uses network_mode: host or an external network without DNS support.

6. Root cause two: external DNS servers and IPv6 timeouts

A second common pattern in DNS issues in Docker networks involves resolving external domains, for example when a container needs to fetch an NPM package or a PHP Composer package from a public registry server. If this resolution fails, it is often not Docker's own DNS at fault, but the external DNS servers the Docker daemon inherited from the host, for example when the host runs in a restrictive corporate network with internal DNS servers that are unreachable from the container's namespace.

A second, very common special case is IPv6-related delay. Some applications ask for an AAAA record by default before falling back to IPv4, and this failed first attempt produces noticeable wait times when IPv6 is absent from the Docker network, which looks like a DNS issue in the Docker network but is actually a protocol fallback timeout. This can be worked around in many applications by explicitly forcing IPv4.


# Check which DNS servers the Docker daemon uses by default
cat /etc/resolv.conf   # on the host, usually inherited by containers

# Force IPv4 resolution to rule out IPv6 fallback delays
docker exec my-app curl -4 --connect-timeout 3 https://registry.npmjs.org

# Compare timing between IPv4-forced and default resolution
docker exec my-app time curl -o /dev/null -s https://registry.npmjs.org

7. Root cause three: DNS caching and alias conflicts

Applications and runtimes frequently cache DNS answers themselves, independent of the operating system. Node.js, JVM-based applications and some PHP extensions keep resolved IP addresses in process memory, sometimes for the entire lifetime of the process. If a database container restarts and gets a new internal IP address, a long-running application with a cached old address can then seemingly lose the connection for no reason, a DNS issue in the Docker network that is actually a caching problem at the application layer.

A second case involves --network-alias: if two different containers accidentally register the same alias in the same network, name resolution returns both IP addresses round-robin, leading to inconsistent behavior that is hard to reproduce. Listing all registered aliases with docker network inspect reliably uncovers such conflicts before they are misdiagnosed as a seemingly random DNS issue in the Docker network.


# List all registered aliases for containers in a network
docker network inspect shop-network \
  --format '{{json .Containers}}' | python3 -m json.tool

# Resolve the same name repeatedly to spot round-robin alias conflicts
for i in 1 2 3 4 5; do
  docker exec my-app getent hosts shop-cache
done

8. Configuring DNS options explicitly

For cases where the default DNS configuration falls short, both docker run and Docker Compose offer explicit options. --dns lets you set an additional or alternative external DNS server for a container, independent of the host configuration. --dns-search adds search domains, so unqualified names automatically get a domain suffix appended before resolution fails. --add-host, or extra_hosts in Compose, inserts static entries directly into /etc/hosts, useful for edge cases that regular DNS in the Docker network cannot cover.

These options should be used sparingly, because they partially override Docker's automatic, self-configuring name resolution and thereby encourage configuration drift between environments. The preferred path remains using the embedded DNS in the Docker network correctly, and reserving external DNS options only for genuine edge cases such as internal corporate domains.


services:
  app:
    image: shop-app:latest
    dns:
      - 8.8.8.8
      - 1.1.1.1
    dns_search:
      - internal.example.com
    extra_hosts:
      - "legacy-api.internal:10.0.5.20"
    networks:
      - shop-network

networks:
  shop-network:
    driver: bridge

9. Default bridge DNS vs custom network compared

The following table compares how DNS behavior differs by network type, a central point for preventing DNS issues in Docker networks up front instead of debugging them laboriously afterward.

Property Default bridge Custom network Typical error
Name resolution by container name Not available Via 127.0.0.11 Name or service not known
resolv.conf content Host's external DNS servers 127.0.0.11 + upstream Wrong expectation of content
Reaction to container restart Only by IP, no auto-update Updated immediately Connection lost after restart
Alias names possible No Yes, --network-alias Round-robin on alias collision
Recommendation Avoid for multi-container setups Standard for all projects -

This overview makes clear that a large share of DNS issues in Docker networks is avoidable once custom networks are used consistently instead of the default bridge. The remaining cases almost always concern external DNS configuration, application-level caching, or alias collisions, all three with clearly identifiable, reproducible symptoms.

Mironsoft

Docker diagnostics, network architecture and production stability

Containers that can no longer find each other by name?

We analyze existing Docker stacks for DNS misconfiguration, fix network segmentation problems and document the root cause instead of patching symptoms.

DNS diagnostics

Systematic analysis of name resolution failures in running stacks

Network refactoring

Migration from the default bridge to custom networks

Monitoring setup

Make DNS timeouts and resolution failures permanently observable

10. Summary

DNS issues in Docker networks can be traced back in most cases to three root causes: containers still running in the default bridge without an embedded DNS server, external DNS servers misconfigured or unreachable from the container's namespace, or applications caching resolved IP addresses across container restarts. The embedded DNS server at 127.0.0.11 reliably resolves container and service names, provided the involved containers run in the same custom network.

Tools like getent hosts, dig and docker network inspect make the diagnosis systematic instead of guesswork. Explicit DNS options like --dns and --dns-search solve edge cases but should stay the exception, so as not to needlessly override Docker's automatic name resolution. Anyone who knows these fundamentals finds DNS issues in Docker networks within minutes instead of debugging in the dark for hours.

Debugging DNS Issues in Docker Networks — Key Takeaways

Embedded DNS server

127.0.0.11 resolves container and service names only within the same custom network.

Most common root cause

Containers in the default bridge without DNS support; the fix is a custom bridge network.

Diagnostic tools

getent hosts, dig and docker network inspect show the cause instead of guessing at it.

Caching traps

Application-side DNS caching survives container restarts and looks like a Docker DNS bug.

11. FAQ: Debugging DNS Issues in Docker Networks

1No name resolution between containers?
Usually default bridge with no DNS support. Move both containers into a custom network.
2What does 127.0.0.11 mean?
Docker's embedded DNS server, resolves container and service names within the same network.
3First connection always slow?
Often an IPv6 AAAA timeout before IPv4 fallback. Force IPv4 explicitly to avoid the delay.
4Check the correct DNS server?
docker exec container cat /etc/resolv.conf, should show 127.0.0.11.
5No nslookup in the container?
Use getent hosts or start a debug container like netshoot in the same network.
6Worked before restart, not after?
Application-side DNS caching of the old IP address, not a Docker DNS bug.
7Setting a custom DNS server?
With --dns in docker run or the dns key in Compose.
8Reaching containers across two networks?
Only if a container joins both networks, DNS only knows its own network.
9Inconsistent connection targets?
Alias conflict: two containers with the same --network-alias, round-robin resolution.
10extra_hosts as a permanent fix?
Only for genuine edge cases, embedded DNS is more robust for container communication.