Error Knowledge Base Docker dial_tcp_connection_refused

Docker dial tcp: connection refused

Docker failed because either the DNS resolver refused the hostname lookup or the registry port refused the TCP connection.

Fix it fast

Most likely: Either Docker's DNS lookup was refused by the configured resolver, or DNS worked and the target registry port actively refused the TCP connection.

1. Confirm this is your error
ERROR: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on 127.0.0.53:53: read udp ...: connection refused
dial tcp: lookup auth.docker.io on [::1]:53: read udp ...: connection refused
dial tcp 10.0.0.20:5000: connect: connection refused
2. Check the cause
docker --debug pull <image>
cat /etc/resolv.conf
nslookup <registry>
nc -vz <registry> 443
curl -vkI https://<registry>/v2/
3. Apply the safe fix
# If the error mentions lookup, :53, 127.0.0.53, 127.0.0.1, or ::1, fix DNS first.
# Restart the resolver, correct Docker daemon DNS, or restart Docker Desktop/WSL after resolver changes.

# If DNS works but the registry port is refused, fix the registry listener, proxy, firewall, security group, or VPN path.
docker --debug pull <image>
4. Verify it works
nslookup <registry>
nc -vz <registry> 443
curl -vkI https://<registry>/v2/
docker pull <image>
Don't use unsafe shortcuts
  • Do not change image tags or credentials until DNS and the registry port are reachable.
  • Do not assume Docker Hub is down when the error points at a local resolver such as 127.0.0.53 or ::1.
  • Do not test only from your laptop if the failing Docker daemon runs in CI, WSL, Docker Desktop, or a remote context.

Where the Request Failed

Read the failed endpoint first. lookup or :53 points to the DNS resolver path. connect: connection refused on :443 or :5000 points to the registry, proxy, firewall, or local service listener.

Restore connectivity to the registry or daemon endpoint

Classify the refusal before retrying. DNS resolver refusals and registry-port refusals have different fixes, even though Docker reports both with dial tcp: connection refused.

If the message contains lookup or :53, fix DNS before changing the image name: restore the local resolver, correct /etc/resolv.conf, update Docker daemon DNS settings, or restart Docker Desktop/WSL after resolver changes.

If DNS succeeds but nc -vz <registry> 443 fails, fix the registry listener, firewall, security group, proxy, or VPN path that is rejecting the connection.

If the failing endpoint is localhost:5000, start or publish the local registry correctly and check whether Docker is resolving localhost to IPv4 or IPv6.

If Docker is configured for a proxy, verify both CLI and daemon proxy settings with docker info and the Docker daemon configuration, because shell proxy variables alone may not affect pulls.

After the direct DNS and port checks pass, retry the original command with docker --debug pull <image> so any remaining error is about auth, TLS, or the image path rather than basic connectivity.

Separate DNS refusal from registry refusal

If the main log is noisy or truncated, these checks let you isolate the failing layer directly and confirm whether you are dealing with configuration, access, trust, or local environment state.

Classify the error first:lookup, :53, 127.0.0.1, 127.0.0.53, or ::1 points to DNS. connect: connection refused with :443 or :5000 points to the registry or proxy port.

For DNS refusal, inspect the resolver from the same shell, container, or CI runner:cat /etc/resolv.conf, nslookup registry-1.docker.io, and nslookup auth.docker.io

On Linux hosts using systemd-resolved, check resolver state with resolvectl status, on Docker Desktop or WSL, restart the VM/desktop layer after resolver changes.

For registry refusal, test the registry port directly:nc -vz <registry> 443 and curl -vkI https://<registry>/v2/

For a local registry, verify both the service and the port:docker ps --filter ancestor=registry and curl -v http://localhost:5000/v2/

If this only fails in CI, run the same DNS and port checks inside the runner job before comparing it with your laptop.

Why It Happens

The same wording can describe two different failures: a refused DNS lookup before Docker knows the registry IP, or a refused TCP connection after DNS already succeeded.

DNS resolver refusal:Docker is asking a local resolver such as 127.0.0.53, 127.0.0.1, or ::1, but that resolver is stopped, misconfigured, or unreachable from the current environment.

Registry port refusal:DNS resolved the host, but nothing is listening on the target registry port, the local registry container is stopped, or a firewall/security group actively rejects the TCP connection.

Proxy/VPN refusal:Docker Desktop, the daemon, or the CI runner is using proxy or VPN settings that differ from your interactive shell, so the registry path is rejected before Docker can read /v2/ metadata.

Environment mismatch:the failing runner, container, or remote Docker context has different DNS, proxy, firewall, or route settings than the machine where the same docker pull works.

Prove the Failing Environment Can Reach It

Do not stop at "the command returned 0 once." Re-run the real workflow from the same machine or runner and make sure the original symptom is actually gone.

For DNS cases, nslookup registry-1.docker.io and nslookup auth.docker.io succeed from the same machine, container, or CI runner where Docker failed.

For registry-port cases, nc -vz <registry> 443 and curl -vkI https://<registry>/v2/ reach the endpoint from that same environment.

For local registries, curl -v http://localhost:5000/v2/ returns an HTTP response and docker ps shows the registry container listening on the expected port.

Re-run the original Docker command and confirm the old connection refused message is gone, if the next error is unauthorized, manifest unknown, or x509, basic connectivity is now fixed and the problem has moved to a different layer.

How resolver and registry ports fail differently

This is the part worth understanding if the quick fix did not hold. It explains what Docker is trying to do at the moment the error appears.

Docker does not contact a registry by name directly. It first asks the configured resolver for the registry or auth-service IP address, then opens a TCP connection to the resolved host and port. When the error contains lookup, :53, 127.0.0.1, 127.0.0.53, or ::1, the refused connection is usually the DNS resolver path, not Docker Hub or the private registry itself.

When the error contains connect: connection refused with a registry IP and port such as :443 or :5000, DNS has already worked and the refusal is coming from the registry endpoint, proxy, firewall, or local service listener.

Prevent Repeat Connectivity Failures

To prevent this, add separate preflight checks in CI for DNS and registry reachability, for example nslookup registry.example.com, nc -vz registry.example.com 443, and curl -f https://registry.example.com/v2/, standardize Docker daemon DNS and proxy configuration across developer machines, CI runners, Docker Desktop, and WSL environments, monitor private registry listeners and firewalls separately from upstream registry health so a local :5000 outage is not mistaken for a Docker Hub problem, and document which environments use a VPN, corporate proxy, or split DNS, and test registry connectivity from those environments after network-policy changes.

Need help or found a mistake? Contact RepoFlow support for questions.

Join our mailing list