getaddrinfo EAI_AGAIN in Docker: DNS was never broken, the resolver's upstream was
Problem
Docker builds and a containerized service intermittently failed DNS with:
Error: getaddrinfo failed: EAI_AGAIN
at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:151:26)
# and the intermittent variant:
FetchError: request to https://registry.npmjs.org/ failed, reason: getaddrinfo EAI_AGAIN registry.npmjs.orgEAI_AGAIN specifically means "resolver answered, but the upstream lookup timed out" — a retry-later error, and retrying usually worked. Reproducing it on demand was impossible, which made it a year-long intermittent tax on every pipeline.
Root cause
Docker's embedded DNS server (127.0.0.11) forwards to the host's configured upstreams. Three compounding weaknesses produce EAI_AGAIN storms:
1. Single upstream: /etc/resolv.conf on the host pointed at one corporate resolver; when it hiccups, every container hiccup in lockstep. 2. Concurrency amplification: npm install fires dozens of parallel lookups; the resolver's rate limit or the docker-proxy's UDP handling drops some, and the client retries into the same storm. 3. ndots quirks with Kubernetes-style resolv.conf: search-domain padding causes multiple lookups per name, multiplying load.
docker compose exec app sh -c 'cat /etc/resolv.conf'
# nameserver 127.0.0.11 — Docker's forwarder; what is it forwarding TO?
… 1 more line in the fix🔒 the fix — including 5 code blocks — is members-only. $1/mo unlocks everything.