Why Docker Hub times out while ordinary web traffic works

Docker image pulls can fail even when browsing, video streaming, and ordinary HTTPS requests appear completely healthy. A terminal may show context deadline exceeded, TLS handshake timeout, net/http: request canceled, or an apparently frozen layer download while the same computer opens websites without hesitation. Searches such as Docker Hub timeout with Clash, Docker pull through TUN mode, and Docker registry proxy not working usually point to a split routing problem rather than a completely unavailable network.

The important distinction is that Docker is not a browser. The Docker CLI normally asks the local Docker daemon to perform the request, and that daemon may run as a privileged system service, inside a virtual machine, or inside a desktop application. It may not inherit the HTTP_PROXY variables from your interactive shell. Even when it does use a proxy, Docker Hub can involve several hostnames: the registry endpoint, authentication service, token issuer, CDN-backed blob storage, and occasionally redirect targets. A rule that only covers registry-1.docker.io can therefore leave the actual image layers on a DIRECT path.

This guide uses an advanced Clash TUN design to make those connections observable and route them consistently. The goal is not to force every packet through a proxy. A better production arrangement keeps local registries, private networks, and approved internal services DIRECT while sending Docker Hub authentication, manifest, and layer traffic through a deliberately selected proxy group. That approach reduces accidental leaks, makes failures easier to classify, and avoids confusing Docker with a broken registry when the real issue is DNS, rule order, or daemon isolation.

The Docker Hub connection path you need to understand

Before changing Clash rules, map the sequence of events. A typical docker pull nginx:latest does more than contact one hostname. The client first communicates with the local Docker daemon. The daemon resolves the registry address, negotiates HTTPS, asks Docker Hub for an authentication challenge, obtains a bearer token, requests a manifest, and then downloads one or more content-addressed layers. Depending on the registry response, the layer bytes may come from a distribution endpoint or a CDN hostname that was not visible in your initial configuration.

This produces a useful troubleshooting principle: a successful login does not prove that image pulls are fully routed. Login can reach the authentication service while the later manifest or blob request is sent DIRECT. Likewise, a manifest may download successfully while a large layer stalls because its CDN route has poor connectivity or because the selected node cannot sustain long-lived transfers.

Stage Typical role What to inspect in Clash
Registry discovery Docker identifies the registry and begins the HTTPS exchange Hostname, DNS answer, SNI, and whether the connection is DIRECT
Authentication Docker requests a token after receiving a registry challenge Authentication hostname and selected proxy group
Manifest request Docker retrieves image metadata and layer digests Rule match, HTTP status, and response latency
Blob transfer Docker downloads large compressed layers from the registry or CDN Destination hostname, sustained throughput, resets, and timeout timing

Use the Clash Connections or Logs view while starting a fresh pull. Search for docker, registry, auth, and the image name, but do not assume the process name tells the complete story. A Docker Desktop VM may appear under a generic service name, while a Linux daemon may display as a system process. The destination domain and rule decision matter more than the friendly process label.

Also record whether the failure occurs at the beginning or after several layers have completed. An immediate timeout usually suggests DNS, authentication, firewall policy, or a completely unreachable route. A failure after hundreds of megabytes points more often to node quality, connection tracking, MTU, idle timeout, or a CDN destination that is missing from your rules. This timing evidence prevents random changes to unrelated settings.

How advanced TUN routing fixes the split path

Clash TUN mode creates a virtual network interface and intercepts traffic at the operating-system routing layer. That is valuable for Docker because the daemon does not need to understand a browser-style system proxy in order for TCP connections to be captured. However, TUN is not magic. It still depends on correct route installation, DNS behavior, sniffing, rule order, and exclusions. A TUN interface that is enabled but not receiving Docker traffic will produce the same symptoms as an absent proxy.

Start with a configuration that makes the routing intent explicit. The exact syntax can vary slightly between Clash-compatible clients and Mihomo builds, so treat the following as a pattern to adapt to your client rather than as a blind universal paste:

tun:
  enable: true
  stack: mixed
  dns-hijack:
    - any:53
    - tcp://any:53
  auto-route: true
  auto-detect-interface: true

dns:
  enable: true
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - https://1.1.1.1/dns-query
    - https://dns.google/dns-query
  fake-ip-filter:
    - '*.lan'
    - '*.local'
    - 'localhost.ptlogin2.qq.com'

rules:
  - DOMAIN-SUFFIX,localhost,DIRECT
  - DOMAIN-SUFFIX,local,DIRECT
  - IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
  - DOMAIN-SUFFIX,docker.io,Docker-Proxy
  - DOMAIN,registry-1.docker.io,Docker-Proxy
  - DOMAIN,auth.docker.io,Docker-Proxy
  - DOMAIN,production.cloudflare.docker.com,Docker-Proxy
  - DOMAIN-SUFFIX,registry-1.docker.io,Docker-Proxy
  - MATCH,Final

The proxy group name in this example, Docker-Proxy, must exist in your configuration. It should normally be a selector or URL-test group containing nodes that support stable HTTPS transfers. Avoid choosing a group solely because it reports the lowest ping. A small ICMP latency does not predict the ability to sustain a multi-gigabyte layer download, preserve long TLS sessions, or handle the registry’s CDN path.

DNS mode, fake IP, and Docker hostname visibility

DNS is one of the most common reasons a TUN configuration appears inconsistent. With fake-IP mode, Clash returns an address from the configured fake range and maps it back to the original hostname. This enables domain-based rules even when an application opens a connection using the returned address. If the Docker daemon bypasses the intercepted resolver, however, it may receive a real address outside the expected policy path. The connection can then hit a GEOIP rule, a local firewall rule, or DIRECT unexpectedly.

Watch the DNS logs during a failed pull. Confirm that the registry and authentication names are resolved by the Clash DNS engine, not by an unrelated local resolver. If your environment has a corporate DNS server, split-horizon records, or a private mirror, do not blindly redirect every query. Add precise fake-IP filters for internal names and keep private registry domains on the resolver that can actually answer them. A public DNS service will not know how to resolve an internal registry, and routing that name through a remote proxy can create an outage that looks like a Docker problem.

Rule order, redirects, and CDN hostnames

Clash evaluates rules from top to bottom. A broad rule such as GEOIP,CN,DIRECT, DOMAIN-SUFFIX,com,DIRECT, or an early provider rule can capture a Docker destination before the specific Docker entries are reached. Put the Docker rules above broad geographic, process, or final matching rules. If you use rule providers, inspect their order rather than assuming a local rule automatically wins.

Do not stop at the familiar Docker names. During a pull, open the Connections panel and identify every destination that appears between the authentication challenge and the layer transfer. Add a narrowly scoped rule for a verified CDN domain only when the logs demonstrate that it is part of your registry flow. Avoid copying a large, unverified domain list from a forum: stale CDN names can route unrelated traffic through the wrong group and make future debugging harder.

A practical repair workflow for Docker and Clash TUN

Follow the steps in order and change one variable at a time. The purpose is to establish a baseline, prove that TUN captures the daemon, then tighten the policy without hiding the original evidence.

  1. Record the exact failure. Save the image name, tag, error text, elapsed time, and the layer that failed. Run a small test image and a known larger image separately so you can distinguish authentication from sustained transfer problems.
  2. Confirm daemon ownership. On Linux, determine whether Docker runs as a systemd service, rootless daemon, or containerized service. On macOS and Windows, identify whether Docker Desktop is using a VM. This tells you whether shell proxy variables are relevant and whether the TUN interface must capture a virtualized path.
  3. Enable TUN with automatic route detection. Turn on auto-route and auto-detect-interface, then verify that Clash reports the expected physical interface. Temporarily disable competing VPN clients, WARP-style tunnels, and endpoint security network extensions while testing.
  4. Test DNS through Clash. Resolve the registry and authentication hostnames while TUN is active. Compare the result with a request made before TUN was enabled. A changed answer is not automatically wrong; what matters is that the answer is consistent with the intended route and that the connection is visible in Clash.
  5. Inspect one fresh pull. Remove any partially cached test layer or use a new tag, then watch Connections in real time. Confirm that registry, authentication, manifest, and blob destinations match the Docker proxy group. If only the first hostname appears, the daemon may be bypassing TUN or the request may be using a destination you did not expect.
  6. Apply a temporary forced rule. For diagnosis, place the verified Docker domains above all broad rules and send them to one reliable proxy group. This is not necessarily your final policy, but it tells you whether routing is the main cause. If the pull succeeds, restore split routing gradually and keep the evidence.
  7. Check long-transfer behavior. Pull an image with several large layers. Observe whether throughput falls to zero, the connection resets, or the node changes unexpectedly. If small manifests succeed but blobs fail, test another node, reduce connection reuse if your client exposes that control, and investigate MTU or provider-side idle limits.
  8. Restart the right components. After changing TUN, DNS, or Docker Desktop networking, restart the affected daemon or desktop VM. Existing connections and cached DNS state can survive a profile reload, making a correct configuration appear ineffective.

For a direct command-line comparison, run Docker with verbose output where your platform supports it, and separately test the registry with a harmless HTTPS request. A successful curl from your shell does not prove Docker works, because the shell and daemon can use different network namespaces, certificate stores, proxy variables, and DNS resolvers. Treat the comparison as evidence about the layers of the stack, not as a final verdict.

If your environment requires explicit daemon proxy settings, configure them according to the Docker installation method and your organization’s policy. For a systemd-managed daemon, proxy variables belong to the service environment, not merely to ~/.bashrc. For Docker Desktop, use its supported proxy controls or rely on a correctly functioning TUN path; mixing explicit daemon proxies with transparent interception can create loops. Never expose a subscription URL, bearer token, or private registry credential in a diagnostic command or public issue.

Production checks: MTU, exclusions, and safe fallbacks

Once the pull works, harden the configuration instead of leaving every Docker destination on Global mode. Keep local addresses, Unix-socket behavior, private registry hostnames, and internal service discovery outside the public proxy path. If your company uses a registry mirror, create explicit rules for its domain and verify its certificate chain. A private mirror that accidentally matches a generic Docker rule may become unreachable when the proxy cannot resolve its internal hostname.

MTU deserves attention when TUN is enabled. Encapsulation reduces the usable packet size, and an incorrect MTU can cause large HTTPS transfers to stall even though small requests succeed. Symptoms include successful authentication, intermittent layer progress, retransmissions, and a connection that freezes at different points on different nodes. Lower the TUN MTU cautiously according to your client and operating system, then retest with a large layer. Do not make an arbitrary change permanent without checking that ordinary LAN traffic and other VPN services still work.

Consider the following operational controls:

  • Use a dedicated group: Keep Docker traffic separate from streaming or general browsing groups so a node change in one activity does not silently affect image pulls.
  • Prefer stable selection: URL-test intervals should be long enough to avoid switching nodes during a layer transfer. Excessive health-check churn can reset sessions.
  • Keep logs temporary: Enable detailed connection and DNS logging during an incident, then reduce verbosity to avoid leaking hostnames, credentials in URLs, or excessive local disk data.
  • Document exclusions: Record why private CIDRs, local DNS names, and registry mirrors are DIRECT. Future rule maintenance is safer when exclusions have an owner and an explanation.
  • Test upgrades: A Mihomo or Docker Desktop upgrade can change TUN stack behavior, VM routing, or DNS handling. Keep a small pull test in your maintenance checklist.

A useful fallback is a local registry mirror or a sanctioned caching proxy. This can reduce repeated external transfers and improve reliability for a team, but it does not remove the need for correct authentication, certificate validation, access control, and upstream routing. Treat a mirror as infrastructure with its own monitoring and storage policy, not as a shortcut around network design.

Frequently asked questions

Why does docker login work while docker pull still times out?

Login and pull do not necessarily use the same complete destination set. Login may reach the authentication service successfully, while the manifest or layer request is redirected to another registry or CDN hostname. Watch a fresh pull in Clash and compare every destination, not just auth.docker.io. Also check whether the login command contacted a different daemon context than the one used by the pull.

Should I use TUN mode or configure an explicit Docker proxy?

Use the method that matches your architecture. Explicit daemon proxy settings are clear and predictable when you control the daemon environment. TUN mode is useful when several applications or virtualized services must share transparent routing and cannot be configured individually. Avoid stacking both without understanding the path, because a daemon proxy may send traffic into a TUN interceptor that sends it back to the same proxy, producing loops or confusing duplicate connections.

Which Docker CDN domains should I add to Clash rules?

There is no permanent universal list. Docker infrastructure and provider responses can vary by region and over time. Capture the hostname from Clash Connections during the failing transfer, confirm that it belongs to the expected registry flow, and add the narrowest rule necessary. A broad wildcard can route unrelated services through the Docker group and may create new latency or privacy issues.

Why do small images work but large images fail?

Small images may complete before a weak route, MTU issue, idle timeout, or unstable node becomes visible. Large layers exercise sustained throughput and expose retransmissions, connection resets, and CDN-specific paths. Compare another proxy node, test the TUN MTU, inspect whether the destination changes during the transfer, and verify that the Docker daemon is not subject to a separate firewall or resource limit.

Some all-in-one VPN clients make Docker troubleshooting difficult by hiding daemon traffic, offering only a single Global switch, or switching nodes aggressively without showing which registry connection failed. In contrast, Clash with advanced TUN routing gives you domain rules, DNS visibility, connection-level evidence, dedicated proxy groups, and explicit DIRECT exclusions, so you can repair the Docker Hub path without tunneling your entire LAN blindly. If you want to reproduce this controlled setup across your own devices, the Clash download page is the natural next step.

Download Clash for free and browse freely →