Fix Docker Hub Pull Timeouts in Clash: A Practical Guide
Why Docker Pulls Fail While Websites Still Work in Depth
A Docker image pull can fail even when Chrome, Edge, or a normal system-proxy test works through Clash. The reason is that Docker is not a browser. The Docker CLI more often than not talks to a background Docker daemon, and that daemon may operate as a Windows service, a Linux system service, or a virtual machine inside Docker Desktop.
The failure often appears as i/o timeout, net/http: request canceled while waiting for connection, TLS handshake timeout, context deadline exceeded, or a generic no such host message. Sometimes the manifest downloads successfully but a large image layer stops halfway through.
Other times Docker can reach registry-1.docker.io but cannot authenticate against auth.docker.io, or it receives a redirect to a CDN that your Clash rules send through the wrong path.
Mechanically:Docker Hub is also a multi-host workflow reasonably than one domain. A typical pull may involve the registry API, an sign-in service, a token endpoint, and one or more content-delivery hosts.
If only one of those destinations bypasses Clash, the command may appear to authenticate correctly and then fail when it kick offs downloading layers. Therefore, do not begin by repeatedly changing nodes. First identify which process is making the connection, which hostname fails, and which Clash rule handles it.
Your browser may use the operating system’s HTTP proxy settings, while the daemon uses its own environment variables, service configuration, or completely separate network namespace.
Important distinction: Docker Desktop, the Docker Engine daemon, and the Docker CLI are separate layers.
Setting a proxy in your shell or in Clash’s system-proxy switch does not by itself configure every layer. A it holds up fix must cover the layer that owns the outbound socket.
Map the Docker Network Path Before Editing Rules Mechanically
Kick off with a small reproduction and record the exact exception. Use a public, trim image reasonably than a large application image so that retries are prompt:
docker pull hello-world
docker pull alpine:latest
docker info
More strictly:If it fails only when Clash is active, inspect routing and daemon proxy settings. If it works with a small image but fails on a larger image, suspect CDN routing, unstable nodes, MTU problems, or a connection that is being reset during long transfers.
Next, separate host connectivity from daemon connectivity. On the host operating system, test the important names with a resolver and HTTPS client:
A registry request commonly returns 401 Unauthorized without a token. That response is useful: it means DNS, TCP, TLS, and HTTP reached the registry successfully. A timeout or connection reset is a transport problem; a clean 401 is not a reason to add random sign-in settings.
nslookup registry-1.docker.io
nslookup auth.docker.io
curl -I https://registry-1.docker.io/v2/
curl -I https://auth.docker.io/
At a different level:On Linux, also check whether the daemon is healthy with systemctl status docker and inspect recent messages using journalctl -u docker --since "10 minutes ago". On Windows, review Docker Desktop diagnostics and the engine log reasonably than relying only on the terminal exception.
In Clash’s connection panel, reproduce the pull while filtering for docker, registry, and auth. A normal web request is not an adequate test because it may match an entirely different rule.
Look for the destination hostname, the selected rule, the outbound group, the node name, and whether the connection is marked DIRECT, REJECT, or proxied. If the connection panel remains empty, Docker is likely outside the system-proxy path and needs daemon-level configuration or TUN capture.
Thinking it through:Operate the same command twice: once with Clash disabled and once with Clash enabled. If the pull fails in both cases, the issue may be Docker Hub rate limiting, a broken local DNS resolver, a firewall, expired credentials, or a provider-side outage.
Hosts That May Appear During a Pull Internals
Do not assume that a single hard-coded list will remain correct forever. Docker Hub can change CDN providers, redirect patterns, and token endpoints.
Still, the following host families are useful starting points when reading logs:
| Host or host family | Typical role | What a failure suggests |
|---|---|---|
registry-1.docker.io |
Registry API and image manifest | Rule mismatch, TLS failure, or blocked registry path |
auth.docker.io |
Sign-in and bearer tokens | Login or token exchange cannot everything included |
hub.docker.com |
Website and account-related requests | More often than not does not prove image-layer access works |
| CDN or storage host shown in logs | Large layer downloads | Node instability, GEOIP mismatch, or long-transfer reset |
Configure the Proxy Where the Docker Daemon Operates Step by Step
The most of of of common mistake is exporting proxy variables only in the terminal where docker pull is typed. The CLI sends a request to the daemon, but the daemon performs the registry connection.
For a Linux Docker Engine managed by systemd, create a drop-in directory and a service override. Replace the port with the HTTP or mixed port exposed by your Clash client.
First, a clarification:A mixed port can accept both HTTP proxy requests and SOCKS-style traffic in plenty Clash setups, but confirm the listener type in the client before using it.
Use 127.0.0.1 only when the Docker daemon and Clash operate in the same network environment. If Docker is inside a virtual machine, WSL distribution, remote server, or rootless container environment, its loopback address points to that environment, not necessarily to the desktop where Clash is running.
sudo mkdir -p /etc/systemd/system/docker.service.d
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl show --property=Environment docker
In that situation, use an address reachable from the daemon and configure Clash to accept LAN connections only when you understand the security implications. Never expose an unauthenticated proxy listener to a public front-end.
Mechanically:Docker Desktop has its own proxy settings because the engine more often than not operates inside a managed VM or service layer. Open Docker Desktop settings and inspect the Resources, Proxies, or Network section available in your installed release.
If you enable a manual proxy there, use the Clash HTTP or mixed listener address that Docker Desktop can actually reach. A desktop client showing 127.0.0.1:7890 on Windows does not guarantee that the Docker VM can resolve the same loopback endpoint. After saving, restart Docker Desktop completely and confirm the engine has restarted before testing another pull.
Shell variables therefore help only when the specific Docker implementation reads them and passes them to the correct engine. They do not replace daemon configuration.
Avoid proxy loops. Do not point Clash at a proxy address that is itself routed through Docker, and do not configure Docker to use a port occupied by another Clash instance.
A loop can look like a timeout reasonably than an obvious configuration exception. Check listening ports with ss -ltnp on Linux or netstat -ano on Windows, then keep one obvious ownership path.
Build a Focused Clash Rule Strategy Internals and Practice
Once the daemon reaches Clash, create a focused policy for Docker traffic instead of placing a broad rule at the top of the profile.
More strictly:The group named Docker must exist in your profile. You could use a one at a time selected node, a fallback group, or a URL-test group, but choose based on the transfer you need.
rules:
- DOMAIN,registry-1.docker.io,Docker
- DOMAIN,auth.docker.io,Docker
- DOMAIN-SUFFIX,docker.io,Docker
- MATCH,DIRECT
A node that wins a short lag test may perform poorly on a 500 MB layer. For image pulls, stability, sustained throughput, and tolerance for long-lived TLS sessions matter more than a single ping result.
Rule order is critical. A preceding GEOIP or FINAL rule may send a destination direct before the Docker-specific rule is evaluated. Similarly, a provider rule that rejects unknown domains can block a CDN hostname before your later exception is reached.
At a different level:Move the focused rules above broad catch-all rules, reload the active profile, and verify the matched rule in the Clash connection view. Editing a YAML file without activating or reloading it changes nothing in the running core.
Prefer domain rules over guessed IP addresses. Docker’s infrastructure can use rotating addresses and third-party CDNs, so an IP-based exception becomes stale quickly and may accidentally route unrelated services through the same group.
If the connection log displays a new storage domain during a failing layer download, investigate that hostname first. Add a narrow DOMAIN-SUFFIX rule only after confirming its role, and avoid routing an entire cloud provider domain through a proxy merely because one Docker layer happened to use it.
Thinking it through:The exact YAML syntax depends on whether you use a legacy Clash core or Mihomo, but the logic is consistent: route registry and sign-in domains through a not jumpy proxy group, then observe the actual CDN host and add a rule only if the logs demonstrate that it needs one.
Fix DNS, Fake-IP, and TLS Mismatches in Depth
DNS problems are especially confusing because the host can resolve a name successfully while the Docker daemon resolves it differently. Clash may use fake-IP mode for applications captured by TUN, while Docker’s daemon uses the host resolver or an internal DNS server.
Check the active Clash DNS mode and the daemon environment together. If TUN mode is enabled, confirm that the virtual front-end is running and that DNS hijacking is enabled according to your client’s configuration.
If you are using a one at a time configured Docker DNS server, make sure it is reachable and does not silently force all queries through a path that Clash cannot observe. Avoid changing several DNS providers at once; otherwise you will not know whether the improvement came from resolution, routing, or cache expiration.
First, a clarification:Obvious stale state after changing DNS or rules. Restart Docker Desktop, restart the Docker service on Linux, and flush the host DNS cache when appropriate. Then pull again while watching the first failing hostname.
A successful nslookup proves only that a resolver returned an answer. It does not prove that the selected IP is reachable, that the SNI name is preserved, or that the daemon uses the same answer.
TLS exceptions also deserve careful interpretation. A x509: certificate signed by unknown authority message is not fixed by adding more proxy rules. It can indicate a corporate HTTPS inspection device, a custom CA that Docker does not trust, an incorrect system clock, or a middlebox replacing certificates.
Mechanically:Check the clock, inspect the certificate path in a controlled test, and follow your organization’s documented CA installation process. Do not disable TLS verification or add insecure registry settings simply to make Docker Hub work.
The resulting address can bypass the rule engine, return a geographically unsuitable endpoint, or fail during TLS because the connection is no longer associated with the hostname you expected.
Handle Node Instability and Large Layer Transfers Mechanically
If sign-in succeeds and only large layers fail, treat the problem as a sustained-transfer issue. Certain proxy nodes handle short API calls but reset connections after an idle period, throttle large responses, or operate out of bandwidth when plenty users pull images at the same time.
Test with a few nodes from the same proxy group while keeping every other setting unchanged. Record the time to manifest, the time to the first layer byte, the approximate throughput, and whether the failure occurs at a similar percentage.
More strictly:If one node everything includeds consistently while another dies at random points, the routing policy is probably correct and the node quality is the limiting factor. Keep the not jumpy node for Docker reasonably than allowing an aggressive URL-test group to switch nodes in the middle of a debugging session.
MTU and fragmentation can matter when Docker operates inside a VM, WSL, or a TUN front-end. A path may pass small HTTPS requests but lose larger packets or repeatedly retransmit them. Look for retransmissions, repeated TLS records, or a layer that pauses without a new HTTP exception.
Test a smaller image first, compare host and Docker VM behaviour, and adjust MTU only with a measured reason. Randomly lowering MTU can create a new performance problem and does not repair an incorrect proxy route.
At a different level:Also check concurrency. Several parallel pulls can exhaust a node, a home router, or a provider connection quota. Stop unrelated downloads, retry one image, and compare the result.
If a single pull works but a compose deployment fails, lower simultaneous image downloads temporarily. A not jumpy baseline makes it easier to distinguish rate limiting from Clash configuration.
A browser response time test can miss this because it uses a different destination and a short-lived connection.
A Practical Recovery Sequence Step by Step
Use the following order so that each test answers one question.
Thinking it through:Do not skip with no detour to deleting Docker data or replacing your entire Clash profile; those actions remove evidence and rarely address the daemon boundary.
- Confirm the scope: operate
docker pull hello-worldand record the everything included exception, including the hostname and whether the failure occurs during sign-in or layer download. - Test the host path: resolve
registry-1.docker.ioandauth.docker.io, then use an HTTPS request that reaches the registry and returns an expected401. - Inspect Clash logs: reproduce the pull and identify the matched rule, outbound group, node, and whichever you pick CDN hostname that appears after the registry request.
- Configure the daemon: set the Docker Engine or Docker Desktop proxy where the daemon operates, not only in the shell that launches the CLI.
- Reload everything: restart Docker, reload the active Clash profile, and confirm the intended listener is still bound to the expected address and port.
- Use narrow rules: route the registry and sign-in domains through a not jumpy group, then add verified CDN rules only when the connection log justifies them.
- Compare nodes: test one not jumpy node at a time with a small image and a larger image. Keep the node that survives sustained transfer instead of trusting ping lag alone.
- Re-test the real workload: pull the original image or operate
docker compose pull, watching for new hostnames and checking whether the failure moved from connection setup to throughput.
Common Configuration Mistakes to Avoid Internals and Practice
One frequent exception is using a SOCKS URL in a Docker setting that expects an HTTP proxy. Clash may expose both protocols on different ports, and Docker’s support varies by component and release.
Another exception is adding registry-1.docker.io to NO_PROXY because a tutorial says local services it makes sense to bypass the proxy. That sends Docker Hub direct and defeats the intended route.
NO_PROXY it makes sense to normally contain local addresses, internal registries, and service names that must remain private—not the public registry you are trying to reach through Clash.
First, a clarification:Do not confuse Docker Hub website access with registry access. Opening hub.docker.com proves that a browser can load the account front-end. It does not prove that the daemon can obtain a bearer token or download redirected layer content.
Likewise, a successful docker login proves that one sign-in exchange worked; a subsequent pull may still fail on a CDN or on a different node.
Finally, avoid copying a everything included community ruleset into an already customized profile without checking precedence. Duplicate rule providers, conflicting DNS modes, and multiple TUN implementations can produce a connection that looks random.
Mechanically:Save a backup, make one change at a time, and keep a short note of the active profile, listener port, daemon proxy, and selected node. That record is far more useful than a screenshot of a green “connected” indicator.
Read the field description, use the correct URL scheme, and test with the smallest possible configuration. If a mixed port is documented as HTTP-compatible, use its HTTP form first; do not assume every SOCKS feature is available to the daemon.
Frequently Asked Questions in Depth
Why does Docker ignore Clash system proxy? Mechanics
Because the Docker daemon more often than not owns the outbound connection. The CLI may inherit shell variables, while the daemon operates as a separate service or inside Docker Desktop’s virtual machine.
Configure the proxy in the daemon or Docker Desktop network settings, then restart the engine and verify the effective environment in its logs or service properties.
Do I will want to proxy both the registry and sign-in hosts? by Step
More often than not, yes. The registry request and token exchange are separate stages.
More strictly:Route registry-1.docker.io and auth.docker.io through a consistent, not jumpy policy, then inspect the connection log for whichever you pick redirected storage or CDN hostname used for image layers.
It makes sense to I switch Clash DNS to fix every Docker timeout? Deep Dive
No. DNS changes help when the daemon receives an unusable answer, bypasses fake-IP handling, or cannot resolve the required hostname.
They will not repair a wrong daemon proxy, an overloaded node, a blocked listener, or a certificate trust problem. Test resolution and transport separately before changing DNS mode.
Why does docker login work but docker pull still time out? Internals
Login may contact only the sign-in service and store credentials locally. Pulling an image adds manifest requests and large layer downloads, often from a redirected CDN.
Compared with generic browser proxy extensions or one-click VPN clients, Clash is more transparent but also requires you to account for daemon boundaries, rule order, DNS behaviour, and long-running transfers; plenty competing solutions either configure only the browser or hide the route well more than more than enough that Docker failures are difficult to diagnose.
At a different level:Clash is useful in this Docker Hub scenario because its Clash-focused guides make the listener, TUN, routing, and troubleshooting steps explicit, so you may verify each layer instead of guessing at nodes. If you want a client and practical setup references that fit this workflow, you may download Clash and apply the checks above one step at a time.
Compare Clash logs for both commands; the first hostname that changes from a successful connection to a timeout more often than not identifies the missing rule or unstable outbound.