Why Docker Pulls Fail While Websites Still Work

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 usually talks to a background Docker daemon, and that daemon may run as a Windows service, a Linux system service, or a virtual machine inside Docker Desktop. 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.

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.

Docker Hub is also a multi-host workflow rather than one domain. A typical pull may involve the registry API, an authentication 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 starts 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.

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 automatically configure every layer. A reliable fix must cover the layer that owns the outbound socket.

Map the Docker Network Path Before Editing Rules

Start with a small reproduction and record the exact error. Use a public, lightweight image rather than a large application image so that retries are quick:

docker pull hello-world
docker pull alpine:latest
docker info

Run 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. 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:

nslookup registry-1.docker.io
nslookup auth.docker.io
curl -I https://registry-1.docker.io/v2/
curl -I https://auth.docker.io/

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 authentication settings. 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 rather than relying only on the terminal error.

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.

Hosts That May Appear During a Pull

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 Authentication and bearer tokens Login or token exchange cannot complete
hub.docker.com Website and account-related requests Usually 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 Runs

The most 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. 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.

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. A mixed port can accept both HTTP proxy requests and SOCKS-style traffic in many Clash setups, but confirm the listener type in the client before using it.

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

Use 127.0.0.1 only when the Docker daemon and Clash run 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. 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 interface.

Docker Desktop has its own proxy settings because the engine usually runs 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.

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 rather than an obvious configuration error. Check listening ports with ss -ltnp on Linux or netstat -ano on Windows, then keep one clear ownership path.

Build a Focused Clash Rule Strategy

Once the daemon reaches Clash, create a focused policy for Docker traffic instead of placing a broad rule at the top of the profile. The exact YAML syntax depends on whether you use a legacy Clash core or Mihomo, but the logic is consistent: route registry and authentication domains through a stable proxy group, then observe the actual CDN host and add a rule only if the logs demonstrate that it needs one.

rules:
  - DOMAIN,registry-1.docker.io,Docker
  - DOMAIN,auth.docker.io,Docker
  - DOMAIN-SUFFIX,docker.io,Docker
  - MATCH,DIRECT

The group named Docker must exist in your profile. You could use a manually selected node, a fallback group, or a URL-test group, but choose based on the transfer you need. A node that wins a short latency 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. 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.

Fix DNS, Fake-IP, and TLS Mismatches

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. 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.

Check the active Clash DNS mode and the daemon environment together. If TUN mode is enabled, confirm that the virtual interface is running and that DNS hijacking is enabled according to your client’s configuration. If you are using a manually 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.

Clear 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 errors 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. 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.

Handle Node Instability and Large Layer Transfers

If authentication succeeds and only large layers fail, treat the problem as a sustained-transfer issue. Some proxy nodes handle short API calls but reset connections after an idle period, throttle large responses, or run out of bandwidth when many users pull images at the same time. A browser speed test can miss this because it uses a different destination and a short-lived connection.

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. If one node completes consistently while another dies at random points, the routing policy is probably correct and the node quality is the limiting factor. Keep the stable node for Docker rather than allowing an aggressive URL-test group to switch nodes in the middle of a debugging session.

MTU and fragmentation can matter when Docker runs inside a VM, WSL, or a TUN interface. 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 error. 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.

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, reduce simultaneous image downloads temporarily. A stable baseline makes it easier to distinguish rate limiting from Clash configuration.

A Practical Recovery Sequence

Use the following order so that each test answers one question. Do not skip directly to deleting Docker data or replacing your entire Clash profile; those actions remove evidence and rarely address the daemon boundary.

  1. Confirm the scope: run docker pull hello-world and record the complete error, including the hostname and whether the failure occurs during authentication or layer download.
  2. Test the host path: resolve registry-1.docker.io and auth.docker.io, then use an HTTPS request that reaches the registry and returns an expected 401.
  3. Inspect Clash logs: reproduce the pull and identify the matched rule, outbound group, node, and any CDN hostname that appears after the registry request.
  4. Configure the daemon: set the Docker Engine or Docker Desktop proxy where the daemon runs, not only in the shell that launches the CLI.
  5. Reload everything: restart Docker, reload the active Clash profile, and confirm the intended listener is still bound to the expected address and port.
  6. Use narrow rules: route the registry and authentication domains through a stable group, then add verified CDN rules only when the connection log justifies them.
  7. Compare nodes: test one stable node at a time with a small image and a larger image. Keep the node that survives sustained transfer instead of trusting ping latency alone.
  8. Re-test the real workload: pull the original image or run docker compose pull, watching for new hostnames and checking whether the failure moved from connection setup to throughput.

Common Configuration Mistakes to Avoid

One frequent error 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. 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.

Another error is adding registry-1.docker.io to NO_PROXY because a tutorial says local services should bypass the proxy. That sends Docker Hub direct and defeats the intended route. NO_PROXY should normally contain local addresses, internal registries, and service names that must remain private—not the public registry you are trying to reach through Clash.

Do not confuse Docker Hub website access with registry access. Opening hub.docker.com proves that a browser can load the account interface. 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 authentication exchange worked; a subsequent pull may still fail on a CDN or on a different node.

Finally, avoid copying a complete 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. 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.

Frequently Asked Questions

Why does Docker ignore Clash system proxy?

Because the Docker daemon usually owns the outbound connection. The CLI may inherit shell variables, while the daemon runs 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 need to proxy both the registry and authentication hosts?

Usually, yes. The registry request and token exchange are separate stages. Route registry-1.docker.io and auth.docker.io through a consistent, stable policy, then inspect the connection log for any redirected storage or CDN hostname used for image layers.

Should I switch Clash DNS to fix every Docker timeout?

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?

Login may contact only the authentication service and store credentials locally. Pulling an image adds manifest requests and large layer downloads, often from a redirected CDN. Compare Clash logs for both commands; the first hostname that changes from a successful connection to a timeout usually identifies the missing rule or unstable outbound.

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; many competing solutions either configure only the browser or hide the route well enough that Docker failures are difficult to diagnose. Clash Official Site is useful in this Docker Hub scenario because its Clash-focused guides make the listener, TUN, routing, and troubleshooting steps explicit, so you can verify each layer instead of guessing at nodes. If you want a client and practical setup references that fit this workflow, you can download Clash Official Site and apply the checks above one step at a time.