When self-hosting services like Uptime Kuma and other containers based on NodeJS - I sometimes came across a persistent connection error along the lines of "getaddrinfo EAI_AGAIN".
At least in my case this seems to be caused by Docker, NodeJS and self-hosted a DNS resolver (like Pihole, Adguard or Blocky) not playing well together.
Although I would get this error on other containers from time to time, I would see it far more often with Uptime Kuma - I think this is do to the nature of this monitoring app. It would more often lookup domains on the DNS system than other containers.
NodeJS does not do any sort of DNS caching at all by default so all queries are passed upstream regardless of TTL.
Self-hosted DNS Problem
While speaking with the maintainers of Uptime Kuma in issue #6824 it seems that some self-hosted DNS systems like Pihole will rate-limit clients and cause this error.
You can help to resolve this by enabling the Uptime Kuma DNS caching setting, or modifying the rate-limit settings in Pihole.
However, my DNS resolver Blocky does not have any rate-limiting turned on.
In my research it seems that Docker will sometimes (I'm not sure when) decide not to use the Docker hosts DNS server (specified by DHCP or by a configuration file) and will silently fall back to a hardcoded Google DNS server 8.8.8.8.
This means you may have had this DNS issue for a while longer that you thought, without noticing the effects since Docker would bypass your own DNS config and use Google.
Not exactly ideal behaviour from Docker, but it does seem to be the "Docker way" to override standard procedures. Just like with their port exposing iptables manipulation regardless of your firewall rules. If this bothers you as much as me, you can use Podman to resolve some of these overreaching behaviours.
Sometime's this internal Google DNS server was not used, and the container was not correctly sending DNS queries upstream to my self-hosted resolver either - resulting in connection errors and the opaque "getaddrinfo EAI_AGAIN" errors.
Specifically Bind IP for Docker DNS Resolvers
It turns out that the simple solution is to make sure you bind the ports of your exposed DNS server (e.g. port 53) specifically to an IP address rather than all IP addresses.
Found the info here on Stack Overflow by citizentwelve.
Otherwise, Docker's network setup can get confused when sending the DNS query traffic and prevent DNS resolutions.
e.g. on your Blocky or Adguard or Pihole Docker Compose file you may have had this:
ports:
- 53:53/tcp
- 53:53/udp
This SHOULD work to allow all traffic on 53 on all IP interfaces, but it does not.
You instead need to specifically set the IP addresses also:
ports:
#- 53:53/tcp
#- 53:53/udp
# https://benhoskins.dev/getaddrinfo-eai_again-dns-error-docker/
# https://stackoverflow.com/a/69994721/614616
- 127.0.0.1:53:53/tcp
- 127.0.0.1:53:53/udp
- 192.168.1.65:53:53/tcp
- 192.168.1.65:53:53/udp
Where "192.168.1.65" is your Docker hosts LAN IP address. I also add some IP's for my internal-VPN DNS resolution too.
After applying this, containers seem to respect the DNS configuration and don't throw the errors any more.
Comments & Questions
Reply by email to send in your thoughts.
Comments may be featured here unless you say otherwise. You can encrypt emails with PGP too, learn more about my email replies here.
PGP: 9ba2c5570aec2933970053e7967775cb1020ef23