Kali Linux on Docker · Part 10 of 16
DNS Troubleshooting From a Kali Docker Container
Series curriculum (16 lessons)
When a container “cannot reach” another service, the failure is almost always name resolution, not the network wire. A Kali container is a perfect vantage point to prove which one it is: it ships with the tools to ask, step by step, “who does this name resolve to, and who is answering?” In this lesson you will read the container’s DNS configuration, resolve a lab service name two different ways, and walk a systematic path from the container all the way out to an external resolver.
Only scan, inspect, or test systems you own or have explicit permission to assess. Everything here targets your own local lab containers and benign public endpoints like
example.com.
The Core Idea: Docker’s Embedded DNS
Docker runs a small DNS server inside every user-defined network. Each container on that network has its /etc/resolv.conf pointed at the special address 127.0.0.11 — Docker’s embedded DNS resolver. That resolver does two jobs:
- Service-name resolution. It knows the name and IP of every container and Compose service on the same user-defined network, so
webresolves to that container’s address automatically. - External forwarding. For anything it does not own (like
example.com), it forwards the query to the host’s configured resolvers.
This behavior is not on by default everywhere. On the default bridge network (what you get with no --network flag), Docker does not provide automatic service-name resolution — containers there can only find each other by IP or the legacy --link flag. On a user-defined network (one you create with docker network create, or any network Compose creates for you), service-name DNS is automatic. That single distinction is the root cause of a large share of “it can’t resolve the other container” tickets.
🛠️ DevOps Perspective — “Expected State vs Observed State” applies cleanly to DNS. Expected:
webresolves to a172.xcontainer address via127.0.0.11. Observed:webdoes not resolve at all. The gap between those two statements tells you where to look — the resolver config, the network attachment, or the name itself — before you touch anything.
Building a Tiny Lab
So the commands have something real to resolve, create a user-defined network and a service named web, then attach a Kali container to the same network:
docker network create labnet
docker run -d --name web --network labnet nginx
docker run --rm -it --network labnet kalilinux/kali-rolling bash
docker network create labnetcreates a user-defined bridge network. This is the step that turns on embedded service-name DNS.docker run -d --name web --network labnet nginxstarts a background (-d, detached) nginx container namedwebon that network. The--nameis the DNS name other containers will resolve.- The Kali
docker runuses--rm(remove the container on exit),-it(-ikeeps STDIN open,-tallocates a TTY so you get an interactive shell), and--network labnetto place Kali on the same network asweb.
From here on, the commands run inside the Kali container.
Command 1: Read the Resolver Config
Start by asking the container what it thinks its DNS server is:
cat /etc/resolv.conf
catprints a file;/etc/resolv.confis the standard Linux resolver configuration that every DNS-aware program reads to learn which nameserver to query.
On a user-defined network you will see something like:
nameserver 127.0.0.11
options ndots:0
That nameserver 127.0.0.11 is the signal you are looking for: this container is wired to Docker’s embedded DNS, so automatic service-name resolution should work. If instead you see your host’s or a public resolver’s address (for example nameserver 8.8.8.8) with no 127.0.0.11, the container is almost certainly on the default bridge — and service names will never resolve there.
🔎 Troubleshooting Tip — Make
/etc/resolv.confyour first stop, always. Ifnameserver 127.0.0.11is present, DNS plumbing is correct and you should suspect the network attachment or the name. If it is absent, stop debugging the name and go fix the network the container is on — no amount of retryingdig webwill help.
Command 2: Resolve a Service Name the Way Apps Do
getent hosts web
getentqueries the system’s Name Service Switch (NSS) — the same resolution path your actual applications use (files, then DNS, in the order/etc/nsswitch.confdefines).hosts webasks it to resolve the hostweb.
A healthy result prints the resolved address and name:
172.18.0.2 web
Because getent follows the real application resolution path, it is the most faithful test of “will my service actually find web?” If getent hosts web succeeds but your app still fails to connect, you have proven the problem is past DNS — a port, a firewall, or the service itself — not name resolution. If getent hosts web prints nothing and exits non-zero, the name did not resolve, and the next command tells you why.
Command 3: Query the Resolver Directly
dig web
digis a DNS lookup tool (install it in Kali withapt-get update && apt-get install -y --no-install-recommends dnsutilsif it is missing). Unlikegetent,digtalks straight to the nameserver in/etc/resolv.confand shows you the full transaction — which server answered, the status code, and the returned records.
Read the SERVER: line and the status: in the header:
SERVER: 127.0.0.11#53confirms Docker’s embedded DNS answered.status: NOERRORwith anANSWER SECTIONmeans the name resolved.status: NXDOMAINmeans the server answered but does not know that name — a strong hint the service name is wrong or the container is on a different network.
dig shines for external names too. Run dig example.com to prove that forwarding to the host’s upstream resolvers works. If dig web succeeds but dig example.com returns SERVFAIL or times out, the embedded resolver is healthy but the host’s upstream DNS is the problem — a completely different fix.
🏭 Why This Matters in Production — In CI and orchestrated environments, “service can’t reach service” pages on-call constantly. Being able to say, in three commands, “resolution is fine, the fault is downstream” (or “the resolver never answered, it’s a network-attachment problem”) turns a 40-minute guessing session into a two-minute diagnosis.
The Resolution Path
Every one of the scenarios below is a break at one specific link in this chain. Knowing the chain tells you which command isolates which link:
Container
↓
Network Attachment
↓
Docker DNS
↓
Service Name
↓
External Resolver
- Container → Network Attachment: is Kali on the same user-defined network as the target? (
docker inspect,/etc/resolv.conf) - Network Attachment → Docker DNS: is
127.0.0.11the nameserver? (cat /etc/resolv.conf) - Docker DNS → Service Name: does the embedded resolver know the name? (
getent hosts web,dig web) - Service Name → External Resolver: for non-container names, does forwarding work? (
dig example.com)
Try It Yourself
With the lab from earlier still running, work the chain top to bottom from inside the Kali container:
🧪 Try It — Run these in order and predict each result before you read it:
cat /etc/resolv.conf— confirmnameserver 127.0.0.11.getent hosts web— expect the container IP and the nameweb.dig web— confirmSERVER: 127.0.0.11#53andstatus: NOERROR.dig example.com— confirm external forwarding returns an answer.- Now break it on purpose:
exit, then start a Kali container with no--networkflag (docker run --rm -it kalilinux/kali-rolling bash) and rungetent hosts webagain. It fails — because the default bridge has no service-name DNS. You just reproduced the single most common cause.
Common Problems
Container cannot resolve another service
This is the headline symptom. Walk the resolution path in order; each step rules out one link.
Symptom: getent hosts web prints nothing, or your app logs could not resolve host: web / Name or service not known.
Diagnostic steps:
- Check the resolver.
cat /etc/resolv.conf. Nonameserver 127.0.0.11? The container is on the default bridge or has custom DNS — service names won’t resolve. Recreate it with--network <your-user-defined-net>. - Check the network attachment. From the host:
docker inspect -f '{{json .NetworkSettings.Networks}}' <container>for both the Kali container andweb. They must list the same user-defined network. A container attached to the wrong network cannot see the other’s name. - Check the service name.
dig webreturningNXDOMAINon a working127.0.0.11almost always means the name is wrong. Confirm the real name:docker ps --format '{{.Names}}'(or, under Compose, the service key incompose.yaml, not the generated container name). Typos and using the container name where a service alias is expected are common. - Isolate external DNS. If container names resolve but
dig example.comfails (SERVFAIL/timeout), the fault is the host’s upstream resolver, not Docker. Test the host directly; fix/etc/docker/daemon.jsondnssettings or the host’s resolvers. - Check the search domain. If short names behave oddly, look at the
searchline andndotsin/etc/resolv.conf. A stray search domain can make a bare name expand into a fully-qualified name that doesn’t exist; try the name with a trailing dot (dig web.) to bypass search-domain expansion and compare. - Check the DNS configuration. A container started with an explicit
--dns 8.8.8.8overrides Docker’s embedded resolver entirely, so it loses service-name resolution while still reaching the internet. Drop the override (or add it only on the daemon for external resolution) so127.0.0.11handles container names.
Mapping each scenario to the path: no 127.0.0.11 = network attachment; wrong network = network attachment; NXDOMAIN = service name; external SERVFAIL = external resolver; odd short-name behavior = search domain; a --dns override = DNS configuration.
💡 Note — Restarting containers can change their IPs, but the name stays stable on a user-defined network — that stability is exactly why you resolve by service name instead of hardcoding an address.
Related Lessons
- Docker networking for Kali — how container networks are wired underneath this.
- User-defined networks — why the embedded DNS only appears here, and how to create one.
- HTTP and API troubleshooting — the next layer up once the name resolves and you need to test the actual endpoint.
- DNS troubleshooting fundamentals — the general resolver, record-type, and forwarding concepts that underpin the Docker-specific behavior here.
What You Learned
- Docker’s embedded DNS lives at
127.0.0.11and provides automatic service-name resolution only on user-defined networks — the default bridge does not. cat /etc/resolv.confconfirms the resolver,getent hosts webtests the real application resolution path, anddig webshows the full transaction and status code.- The resolution path — Container → Network Attachment → Docker DNS → Service Name → External Resolver — lets you isolate a failure to one specific link.
NXDOMAINpoints at a wrong service name or wrong network; a workingdig webbut failingdig example.compoints at the host’s upstream resolver.- Search-domain expansion and explicit
--dnsoverrides are subtler causes worth checking once the obvious two are ruled out. - Systematic “Expected vs Observed” thinking turns a vague “can’t reach the service” into a precise, one-link diagnosis.
Recommended Reading
Affiliate Disclosure: Some links on this page are affiliate links. If you purchase through one of these links, DevOps AI Toolkit may earn a commission at no additional cost to you. See our affiliate disclosure.
← Back to Kali Linux on Docker Back to Kali Linux