Why Docker Hub Pulls Can Stall While Clash Looks Connected
A Docker image pull is not a single browser-like request. The Docker CLI asks a Docker Engine to do the work, and the engine then contacts the registry, requests an authorization token, downloads image manifests, and fetches image layers from storage or delivery hosts. A failure at any one of those stages can look like “Docker Hub is down,” even when ordinary websites load normally and the Clash dashboard shows an active node. The important first question is not simply whether Clash is connected; it is which process is making the failing connection, and which route that connection actually takes.
This distinction catches a common troubleshooting trap. A proxy setting in your terminal may affect curl or a command-line client, but a Linux Docker Engine normally performs image downloads as a separate service. Docker Desktop adds another boundary: the engine runs inside its managed environment, so the host operating system’s proxy state and the engine’s effective proxy configuration may not be identical. You can therefore make a test request succeed from your shell while docker pull continues to time out.
A timeout also does not identify its own cause. It may mean the selected Clash node is unhealthy, a routing rule sent a registry host to DIRECT, DNS returned an unreachable address, a firewall blocked the connection, or the daemon never received a usable proxy setting. Before changing several settings at once, record the exact error, the image name, the approximate time, and whether the failure occurs during token authorization or layer download. Those clues make the next test much more useful than repeatedly restarting Docker and switching random nodes.
Identify the Failing Hop Before Editing Configuration
Start with the complete error from the terminal. Messages such as i/o timeout, context deadline exceeded, and connection reset by peer point toward transport trouble, but they do not tell you whether the failure occurred at the registry, token service, or layer host. An error mentioning a name-resolution failure deserves a DNS check first. An authorization message, by contrast, can indicate a login, credential, or token problem rather than an unreachable network. Save the output instead of reducing every failure to “pull is broken.”
Check which Docker context is active and which engine receives the request. Desktop users may have more than one context available, while Linux users may be talking to a local daemon or a remote engine. Run docker context show and docker info, then confirm that the target engine is the one whose proxy and network settings you intend to troubleshoot. If a remote context is active, changing Clash on your laptop will not automatically change the network path used by the remote machine.
Compare a registry endpoint check with an actual image pull. For example, curl -v https://registry-1.docker.io/v2/ normally receives an HTTP 401 Unauthorized response when it can reach the registry without providing registry credentials. In this specific test, that response is useful: it shows that DNS, TCP, TLS, and an HTTP exchange with the registry endpoint completed. It does not prove that the Docker daemon can reach the token service or every host used for image layers, so treat it as one diagnostic rather than a full pull test.
If the shell check succeeds but a pull fails, compare the request paths rather than concluding that Docker is ignoring the result. The shell’s curl may use environment variables, while the engine may use a service-level proxy, Docker Desktop’s proxy settings, or no proxy at all. Conversely, if both tests fail, inspect the node and route before rebuilding Docker configuration. A short, controlled comparison with one known-good node can separate a bad exit from a daemon configuration issue.
Check the Clash Node, Proxy Mode, and Routing Rules
First confirm that the selected proxy group contains a usable node and that the node can establish ordinary HTTPS connections. Use the client’s connection log or traffic view while repeating a small test. Look for requests to registry-1.docker.io, auth.docker.io, and any additional registry or layer-delivery host shown in the error or connection log. The precise set of layer hosts can vary, so do not assume that a successful registry request means every download destination follows the same rule.
Next inspect the matching rule for those hostnames. A broad rule such as DOMAIN-SUFFIX,docker.io,DIRECT can override your expectation that Docker traffic should use a proxy, depending on where it appears in the rule list and which policy group it targets. A catch-all MATCH rule may send unclassified hosts to a different group from the registry itself. Put deliberate Docker-related rules above broader matches when your network policy requires them, and keep the destination group consistent enough that the registry, authorization, and layer requests do not unexpectedly take different paths.
Do not begin by routing all traffic through a proxy as a permanent fix. A temporary test using a known-good proxy group can help isolate the problem, but broad routing can affect local services, corporate networks, and applications that should remain direct. If you use rule providers, check whether their latest refresh changed the effective order or group assignment. A configuration that worked yesterday may behave differently after a provider update, even though no one edited the main YAML file.
Also verify the proxy type supported by the application. Clash commonly exposes HTTP, SOCKS, and mixed listeners, but Docker Engine’s daemon proxy settings are intended for HTTP and HTTPS proxy URLs; a SOCKS listener is not automatically interchangeable with an HTTP proxy. If Docker is pointed at a port that accepts only SOCKS, a connection can fail even though a SOCKS-aware test tool works. Use a suitable HTTP or mixed listener where supported, and confirm the port in the Clash client instead of relying on a remembered default.
Configure the Proxy for the Docker Engine
The right configuration point depends on the engine. In Docker Desktop, check the application’s proxy or network settings and confirm whether it uses the operating system proxy, a manually configured proxy, or a managed setting. Apply a change using the controls provided by your installed Desktop version, then restart or apply the engine when prompted. Do not assume that enabling a proxy in a browser, changing a system setting, or exporting a variable in one terminal automatically changes Docker Desktop’s engine traffic.
On a Linux host running Docker Engine as a service, configure the daemon’s proxy using the method supported by the installed Engine version, such as a systemd service drop-in or the daemon’s supported proxy configuration. The proxy URL should point to an address reachable from the daemon’s network namespace. A listener bound only to a loopback interface inside a different container or virtual machine may not be reachable from the engine. After changing daemon configuration, reload the service manager if required and restart Docker during a suitable maintenance window.
Shell variables such as HTTP_PROXY, HTTPS_PROXY, and NO_PROXY are useful when the process making the request reads them. They are not a universal switch for every Docker component. In particular, the Docker CLI communicates with the daemon, and image transfer is normally performed by the daemon. Setting variables in your interactive shell can help a shell-based test while leaving the daemon’s outbound path untouched. Use a correctly scoped daemon or Desktop setting for pulls, and keep shell variables for tools that actually inherit them.
Treat proxy credentials carefully. Avoid pasting passwords or long-lived tokens into screenshots, support tickets, shared YAML files, or shell history. If the proxy requires authentication, use the configuration mechanism intended for your Docker environment and check its documentation for how credentials are stored and passed. Add only destinations that genuinely need direct access to NO_PROXY; an overly broad exclusion can silently bypass Clash for the very registry traffic you are trying to test.
After the change, verify that Docker is using the intended context and daemon, then inspect Docker’s service logs if the pull still fails. On a systemd-based Linux host, journalctl -u docker can provide useful timing and connection details. Logs may reveal that the daemon rejected a proxy URL, could not resolve the proxy hostname, or reached one endpoint before timing out at another. Redact credentials and sensitive internal hostnames before sharing diagnostic output.
Verify DNS, TUN Capture, and Hostname Resolution
DNS can make a healthy proxy appear unreliable when different components resolve the same name through different paths. Check that the host running the engine can resolve the registry and the proxy itself. If the engine uses a hostname for its proxy, failure to resolve that hostname can prevent every proxied request from starting. When troubleshooting, compare repeated lookups rather than trusting a single successful result; changing addresses or inconsistent answers can expose a resolver or network-path problem.
Clash DNS settings and system DNS settings are not necessarily identical. A client may use its own resolver rules while the Docker daemon or Desktop environment uses another resolver. Inspect the Clash connection log and DNS configuration, and confirm that the hostname involved in the failure is not being sent to an unintended resolver or receiving an unusable answer. Avoid copying a public DNS address into every configuration as a reflex: managed networks, local zones, split DNS, and organizational policy may require a particular resolver.
TUN mode is one way to capture traffic from applications that do not use a conventional HTTP proxy, but enabling it is not automatically required for Docker. If Docker’s daemon has a valid HTTP proxy configuration and can reach the Clash listener, that explicit proxy path may be sufficient. TUN becomes relevant when the engine’s traffic is otherwise outside the operating system proxy path, or when your chosen setup is designed to capture outbound connections transparently. Whether a particular Docker Desktop or Linux arrangement is captured depends on its virtual networking and platform details.
If you test with TUN, make one change at a time. Confirm that the interface is active, the client has the required permissions, and no other VPN or network filter is competing for the default route. Then watch the Clash connection log while triggering a pull. If no Docker-related connection appears, the traffic may not be entering the TUN path, or the failure may occur before a connection is attempted. If connections appear but are routed incorrectly, adjust the matching rules rather than repeatedly toggling TUN.
Be especially cautious with remote Docker engines, virtual machines, and containerized daemons. The host’s TUN interface may not capture traffic inside another network namespace, and a loopback address refers to the current environment—not necessarily the machine where Clash is listening. Identify where the engine runs, how it reaches the host, and which address is valid from that environment. This simple topology check often explains why 127.0.0.1 works in a laptop terminal but fails when configured for a daemon in a VM.
Run a Controlled Pull Test and Read the Result
Once you have checked the route, proxy, and DNS, run a pull that is small and repeatable, such as docker pull hello-world. Record the start time and watch the Clash connection log at the same time. A successful pull is stronger evidence than a browser test because it exercises the Docker Engine’s actual request path. If it fails, preserve the full error and note whether the engine received a manifest, began downloading layers, or stalled before any visible progress.
Use a simple comparison matrix rather than changing several variables simultaneously. A shell request through the Clash HTTP listener tests that listener from the shell’s network environment. A registry check without an explicit proxy tests the shell’s default route. The actual Docker pull tests the engine’s current configuration. If only the first works, investigate the engine’s proxy or network namespace. If the registry check works but the pull fails, focus on Docker’s daemon path, token access, and layer destinations. If all three fail, start with node health, DNS, and routing.
| Observation | Likely area to inspect | Next useful check |
|---|---|---|
| Shell request works, Docker pull times out | Engine or Desktop proxy configuration | Confirm the active context and daemon settings |
| Registry endpoint responds, but layers stall | Layer-delivery route or a later hostname | Inspect Clash logs for the failing destination |
| Registry and proxy hostnames fail to resolve | DNS configuration or resolver reachability | Compare lookups from the engine’s environment |
| No related traffic appears in Clash logs | Traffic is bypassing the listener or TUN path | Check the engine’s network location and proxy settings |
After the controlled pull succeeds, repeat it once and then try the image that originally failed. If the test image works but the original does not, compare registry namespaces, image manifests, authentication requirements, and the actual hosts shown in the logs. A public image can test basic reachability, but it cannot prove that a private registry credential is valid or that a particular image’s layer host is reachable. Keep these conclusions narrow so that a network fix does not distract from a separate authorization or image-name issue.
When a configuration change appears to fix the problem, record what changed: selected Clash group, relevant rule, proxy listener, daemon setting, DNS behavior, or TUN state. That note makes future regressions easier to diagnose, especially after a client update or rule-provider refresh. Revert temporary broad routing if it is no longer necessary, and avoid leaving debug credentials or proxy URLs with secrets in files that are committed to a repository.
Docker Hub Pull Timeout FAQ
Why does curl work through Clash while docker pull still times out?
The two commands may use different network settings and different processes. Your shell’s curl can honor environment proxy variables, while the Docker Engine performs the pull using its own daemon or Desktop proxy configuration. Confirm the active Docker context and configure the engine that actually performs the download; do not treat a successful shell request as proof that the daemon uses the same proxy.
Do I need to enable TUN mode for Docker Hub?
Not necessarily. An engine that can reach a suitable Clash HTTP proxy listener may work without TUN. TUN can help in setups where the engine’s connections are not using an explicit proxy, but capture depends on the engine’s host, virtual networking, and platform. Check the connection log and network topology before making TUN the default answer.
Is an HTTP 401 response from the Docker registry a failure?
Not for the unauthenticated endpoint check described here. A 401 Unauthorized response from https://registry-1.docker.io/v2/ can confirm that the request reached the registry and received an HTTP response. It does not prove that Docker can obtain a token, authenticate to a private repository, or download every layer.
What should I do if switching Clash nodes fixes the pull temporarily?
Treat that as evidence about the route, not as proof that the whole configuration is correct. Check whether the old node could reach the registry, token, and layer endpoints; compare the effective routing rules; and confirm that the new node is not merely masking a DNS or daemon-proxy mismatch. A stable fix should identify why the prior path failed and remain reliable after the next rule or client update.
Some general-purpose VPN clients make it easy to change a device-wide route but offer less visibility into which Docker hostname matched which policy; manual proxy variables are also easy to set in the wrong shell and leave the daemon untouched. For this kind of diagnosis, Clash V.CORE provides a practical balance: inspectable rules, selectable proxy groups, connection visibility, and options for proxy or TUN workflows, so you can test the engine’s path without blindly tunneling everything. If you want those controls available while checking Docker Hub pulls, download Clash V.CORE and configure it for your network and platform.
// Editor's Pick
Make Docker Hub Routing Easier to Diagnose
Use clear proxy groups and visible connection activity to check where Docker registry traffic is going.
- Inspect routing decisions for registry hostnames
- Switch proxy groups for controlled comparisons
- Review connection activity during image pulls
- Choose proxy or TUN workflows for your setup