Align Docker Desktop With Clash on Windows 11: Proxy and DNS Setup (2026)
You already run Clash on Windows 11, browsers load foreign sites, and your subscription looks healthy—yet docker pull, docker compose builds, or apt-get inside a Dockerfile still time out or resolve the wrong path. That mismatch is expected: Docker Desktop does not read the same “system proxy” story as Edge, and it is not the same network namespace as a bare WSL2 shell. This guide walks a host-aligned setup: discover the real HTTP/HTTPS listener your core exposes, bridge into the Linux VM with host.docker.internal, persist daemon.json proxy fields, align DNS with how your profile resolves registry names, and propagate proxy variables into container build steps so image layers and package managers stop fighting you.
Why Docker Desktop ignores “the proxy that already works in Chrome”
Docker Desktop on Windows runs the engine inside a lightweight Linux VM (historically Hyper-V or WSL2 backend, depending on your settings). When you enable system proxy in a GUI client such as Clash Verge Rev, WinHTTP-aware desktop apps may follow the OS, but the Docker engine’s outbound connections originate from that VM. They do not magically inherit per-user Internet Options unless you teach Docker explicitly. Meanwhile, your Clash listener on 127.0.0.1:PORT lives on the Windows host; from inside the VM, loopback is the wrong address—you need a stable hostname that resolves to the host, which Docker documents as host.docker.internal on recent builds.
This article complements our WSL2 Git and npm proxy guide: many engineers run both WSL distros and Docker Desktop on one laptop, and the fixes are related but not interchangeable. WSL shells need the Windows host IP; Docker Desktop needs GUI-level proxy configuration plus engine JSON when the UI alone is insufficient. If inbound access to your mixed port is part of the story—because something other than loopback must reach Clash—pair this walkthrough with LAN proxy and Windows Defender Firewall rules so you are not debugging two unrelated blockers at once.
Prerequisites: confirm the host side before you touch Docker
Open your client, verify the core is running, and read the actual mixed or HTTP port from the settings panel—not a forum post from 2019. Templates still cite 7890 while your active profile might expose 7897 or another value. Write it down; half of “Docker ignores the proxy” tickets are wrong-port copy-paste. If you are new to the Windows-first flow, Clash Verge Rev on Windows 11: first install establishes baseline vocabulary before you stack containers on top.
Because the Docker VM must open TCP to a listener that is not strictly loopback-only, enable whatever your GUI calls Allow LAN / bind beyond 127.0.0.1 for the port you will reference from host.docker.internal, then confirm Windows Firewall allows inbound to that port on trusted networks. Without that, curl from inside a test container will fail before you even debate YAML rules.
Step 1 — Set Docker Desktop’s manual proxy (GUI path)
Open Docker Desktop → Settings → Resources → Proxies (wording may shift slightly across versions). Enable manual proxy configuration and set both HTTP and HTTPS to point at your host listener through the special DNS name:
http://host.docker.internal:7897
Use the same http://host.docker.internal:PORT value for both the HTTP and HTTPS proxy fields when Docker Desktop shows two boxes—the outbound HTTPS traffic to registries still tunnels through your local HTTP proxy via CONNECT. Replace 7897 with your real mixed or HTTP port. Apply & restart when Docker prompts.
Sanity-check from PowerShell on Windows after restart: docker pull hello-world. If it still fails, do not jump to YAML yet—capture whether the failure is TLS handshake, TCP timeout, or DNS—three different knobs.
For a narrower connectivity proof before you pull multi-gigabyte layers, run a tiny diagnostic container that only exercises TCP to the host proxy: docker run --rm curlimages/curl curl -sS -o /dev/null -w "%{http_code}" --proxy http://host.docker.internal:7897 https://www.example.com (adjust port). A quick 200 or 301 response tells you the VM can reach Clash; a hang points to firewall or bind address, not registry rules.
Step 2 — Persist engine-level proxies in daemon.json
The GUI is convenient, but teams often need the same values in the engine configuration for reproducibility. Docker’s JSON file accepts a proxies object with http-proxy, https-proxy, and no-proxy keys. On Docker Desktop you can edit via Settings → Docker Engine or by writing the file the UI merges—prefer the in-app editor so the service restarts cleanly.
{
"proxies": {
"http-proxy": "http://host.docker.internal:7897",
"https-proxy": "http://host.docker.internal:7897",
"no-proxy": "localhost,127.0.0.1,::1,host.docker.internal"
}
}
Extend no-proxy with your private registry hostnames if you mirror images internally; otherwise those pulls will unnecessarily detour through Clash and confuse split rules. After editing, restart Docker and re-run a pull you know should traverse the proxy. The daemon.json approach is the anchor keyword many searches use—keeping this block in version-controlled notes helps onboarding peers who only see symptoms in CI.
Step 3 — DNS: registry names, fake-ip, and where Docker resolves
Image pulls fail in two loud ways: TCP never connects, or names do not resolve. Clash profiles frequently enable fake-ip mode for speed on the Windows host: applications ask for an address, receive a synthetic IP from a pool, and the core learns the real destination from SNI or sniffing. Docker’s embedded resolver and the registry client inside the engine may not participate in that choreography the same way a browser on Windows does. If you observe odd partial failures—some tags pull, multi-arch manifests stall—collect nslookup registry-1.docker.io from a throwaway container and compare with your host resolver path.
Practical alignment strategies (pick one coherent stack, not all at once):
- Let Docker Desktop use explicit upstream resolvers via engine JSON
"dns": ["1.1.1.1","8.8.8.8"]when your goal is predictable public resolution for registry CDNs. - If your network mandates split DNS for internal mirrors, add those search domains or server lists in Docker Desktop’s DNS UI so the VM matches IT expectations.
- When fake-ip on the host creates confusion, test a profile branch with redir-host or a DNS mode your team documents, then compare logs—not superstition.
Vocabulary for deeper edits lives in the site-wide Clash tutorial; this Docker article stays focused on transport and resolver parity, not re-teaching every YAML keyword.
Step 4 — docker compose and build-time proxies
docker compose build runs buildkit or legacy builders inside the same ecosystem; the engine proxy helps daemon pulls of base images, but RUN apt-get update inside a Dockerfile still needs environment variables unless each line disables the network. Standard pattern: declare build arguments and forward them in compose:
# Dockerfile excerpt
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY
ENV HTTP_PROXY=$HTTP_PROXY HTTPS_PROXY=$HTTPS_PROXY NO_PROXY=$NO_PROXY
# compose excerpt
services:
app:
build:
context: .
args:
HTTP_PROXY: http://host.docker.internal:7897
HTTPS_PROXY: http://host.docker.internal:7897
NO_PROXY: localhost,127.0.0.1
For one-off interactive builds, you can export the same trio in PowerShell before docker build; compose merely makes repetition honest. Remember that localhost inside a build step refers to the build container, not your Windows host—do not point tools at 127.0.0.1:7897 unless a local sidecar actually listens there in that stage.
Step 5 — Private registries, mirrors, and authentication
Corporate registries often live on RFC1918 addresses or internal DNS names. Add them to no-proxy in both Docker Desktop and compose args so traffic does not traverse Clash at all, then handle TLS trust inside the image if your company re-signs certificates. When authentication fails with 401 while connectivity is fine, the proxy is usually innocent—refresh tokens and credential helpers—but mixed proxy environments occasionally strip headers; test docker login with verbose output before you rewrite rules.
Step 6 — WSL2 backend vs Hyper-V: does it change the proxy URL?
Microsoft and Docker have iterated on backends; host.docker.internal is the portable default on current Docker Desktop releases. If you run an unusual build where that hostname fails, consult Docker’s release notes for your exact version—some teams temporarily map the Windows host IP explicitly, but that IP can change when you switch Wi-Fi networks, so treat static IPs as a last resort compared with the hostname.
Troubleshooting matrix (symptom → first check)
Connection refused to host.docker.internal:PORT
Wrong port, core not running, or listener bound to loopback only on Windows. Re-check mixed-port, enable LAN binding, and firewall allow rules.
TLS handshake errors during pull
Mixed TLS inspection or MITM devices: trust the corporate root inside Docker’s VM (advanced) or exempt registry hosts per policy—not something to “fix” by disabling encryption blindly.
DNS timeouts for registry hostnames
Align Docker engine DNS with a resolver that can reach authoritative servers; revisit fake-ip interactions on the host and compare container nslookup output with Windows.
Only apt/yarn/cargo fails during build
Engine pull works; build steps ignore daemon proxy. Add ARG/ENV as above or tool-specific config files (apt.conf, npmrc) inside the Dockerfile.
Security posture: avoid spraying open proxies on untrusted Wi-Fi
Binding Clash beyond loopback and punching firewall holes increases exposure—reasonable at home or office VLANs, risky on hotel networks. Pair allow rules with network awareness; disable LAN exposure when you close the laptop. Docker’s VM reaching out through your proxy also means any container compromise could abuse that path—keep images patched and registries pinned.
Closing: one mental model
Docker Desktop is not “just another app on Windows”; it is a Linux engine behind a VM boundary. Aligning it with Clash means giving that VM the same structured hints you would give a remote coworker: correct hostnames, explicit HTTP/HTTPS proxy URLs, a thoughtful no-proxy list, DNS that matches your registry reality, and build arguments so container build steps inherit the same path as image pull operations. Compared with toggling random checkboxes, that sequence turns intermittent failures into reproducible infrastructure—especially next to our WSL2 proxy article for shell-native workflows.
When you want a maintained desktop client to anchor the stack, use this site’s download page as the primary install path—Download Clash for free and experience the difference.