DEV Community

James Joyner
James Joyner

Posted on

DNS Troubleshooting with dig: The Commands DevOps Engineers Actually Need

A surprising share of "the app is down" pages resolve to a name-resolution problem, not a broken service. The service is fine; the client can't turn a name into an address. dig is the precision tool for proving that in seconds instead of guessing.

Think about it as a resolution chain, not "is DNS broken"

When a name fails, work the chain: which resolver did the client ask, what did that resolver return, and does it match what authoritative DNS actually says? Most incidents live in the gap between those three. The method is boring and reliable: observe the symptom, form a hypothesis about where in the chain it breaks, test with one query, read the evidence, fix, then validate.

The single most important habit: query the name from the same host and the same resolver the app uses. Running dig from your laptop proves nothing about what the pod or VM sees.

The record types worth knowing

You don't need all of them, but you need to recognize them:

  • A / AAAA — name to IPv4 / IPv6 address. The usual suspect.
  • CNAME — an alias pointing at another name. A stale or wrong CNAME sends traffic somewhere unexpected.
  • MX — mail routing. TXT — SPF, DKIM, domain verification, and other metadata.
  • NS — which servers are authoritative for a zone. SOA — the zone's serial and TTL defaults; the serial tells you whether a change has propagated.
  • PTR — reverse lookup, IP back to name.

The commands that actually earn their place

Start with the quick answer, then get precise.

dig +short api.internal.example.com
Enter fullscreen mode Exit fullscreen mode

+short strips everything except the answer. If it prints an IP, resolution works from this host. If it prints nothing, you have a real failure to chase. Empty output is a signal, not an error.

dig api.internal.example.com A
Enter fullscreen mode Exit fullscreen mode

The full form. Read the status in the header: NOERROR with an ANSWER section is good; NXDOMAIN means the name genuinely doesn't exist; SERVFAIL points at a broken upstream or DNSSEC issue. Also note which SERVER answered at the bottom — that's the resolver you're actually testing.

dig -x 10.20.30.40
Enter fullscreen mode Exit fullscreen mode

Reverse lookup (PTR). Handy when logs show an IP and you need the name, or when validating that forward and reverse records agree.

dig +trace api.example.com
Enter fullscreen mode Exit fullscreen mode

+trace walks delegation from the root servers down, showing each handoff. Use it when a name works from one resolver but not another — it reveals whether the authoritative servers themselves disagree with your cache.

resolvectl status
Enter fullscreen mode Exit fullscreen mode

On systemd hosts, this shows the actual resolver and search domains in effect per interface. This is the ground truth that /etc/resolv.conf often only hints at, especially when systemd-resolved owns the stub at 127.0.0.53.

Real scenarios, and how to read them

Wrong A record. dig +short returns an IP, but it's the old one. Confirm authoritative truth with dig @<authoritative-ns> name A and compare to the zone's SOA serial. If authoritative is correct but your resolver isn't, you're looking at caching.

Stale cache / TTL. A record changed an hour ago but clients still hit the old address. Check the TTL counting down in the ANSWER section — a long TTL means old answers linger. Query the authoritative server directly to confirm the new value, then wait out or flush the cache rather than "restarting things."

Wrong resolver in /etc/resolv.conf. The app queries a resolver that can't see internal zones. dig shows the wrong SERVER at the bottom of its output. Cross-check with resolvectl status. This is common on cloud VMs where DHCP overwrites resolver config.

Search-domain surprises. dig +short api returns nothing but dig +short api.internal.example.com works. A bare name gets search domains appended by the resolver, and dig does not apply them the way your app's resolver library does. Always test both the short name and the FQDN.

Container DNS. Inside Docker, /etc/resolv.conf points at the embedded resolver 127.0.0.11, which forwards to the host and resolves other containers by name. In Kubernetes, pods use cluster DNS (CoreDNS) with search domains like svc.cluster.local. The rule holds: dig from inside the container or pod, not from the host. A name that resolves on the node but not in the pod is a cluster-DNS or search-domain issue, not a broken app.

I wrote this up as a full, reproducible walkthrough — resolver chain, capture, and fixes — in the DNS troubleshooting lesson, part of a 15-lesson networking series aimed at DevOps and DevSecOps troubleshooting. There's also a container-focused DNS lesson that goes deeper on the 127.0.0.11 resolver and cluster DNS.

One note on ethics: only inspect, query, or capture DNS traffic on systems you own or are explicitly authorized to assess. This is defensive infrastructure validation, not reconnaissance.

The takeaway

DNS failures feel mysterious because people guess. dig, run from the right host against the right resolver, turns guessing into evidence: you can see the status code, the resolver, the TTL, and the delegation path in one command each.

If you want the hands-on version, the DNS troubleshooting walkthrough steps through each scenario end to end — and the site has more free, hands-on Kali learning paths built specifically for DevOps engineers.

Top comments (0)