一、为何系统代理开了,容器仍可能直连
Docker 容器运行在 Linux 网络命名空间里,拥有独立的回环地址与虚拟网桥;Windows 的系统代理(WinINet / 系统设置)主要影响遵循系统代理栈的桌面应用,而不会自动注入到每个容器的进程环境中。许多镜像里的 apt、pip、npm、git 默认不读 Windows 注册表里的代理项,除非你显式传入环境变量或在镜像里配置。
因此会出现典型现象:浏览器访问 GitHub 正常,而 docker compose build 拉基础镜像或 pip install 一直超时。这与 WSL2 里 localhost 不等于宿主机 是同一类「边界认知」问题,只是对端从 WSL 换成了 Docker Desktop 的 Linux VM。解决思路一致:先找到从容器视角可达的宿主机地址,再把代理端口对齐到 Clash 的混合端口。
二、先对齐 Windows 上 Clash 的监听与防火墙
容器要通过 TCP 连到宿主机上的 Clash,前提是 Clash 在 Windows 上正在监听你打算使用的端口(常见为 混合端口,同时承载 HTTP 与 SOCKS),且监听范围不能仅限 127.0.0.1。若只绑定回环地址,来自 Docker 网桥的连接会被拒绝。请在客户端中开启类似「允许局域网 / Allow LAN」或把绑定地址设为 0.0.0.0(具体名称因 Mihomo 内核与 GUI 而异),然后重载配置。
第二层是 Windows Defender 防火墙:从容器发往宿主机的连接属于入站。若未为 Clash 主程序或对应 TCP 端口放行,会出现连接超时而非立即拒绝。更细的图示与规则命名可参考 Windows 11 混合端口与防火墙 一文,把其中的「局域网设备」换成「Docker 虚拟网卡」即可。
在继续之前,建议在 PowerShell 里用 curl.exe -v -x http://127.0.0.1:你的混合端口 https://www.example.com 确认本机到 Clash 的通路正常。若此处失败,应先修 Windows 侧,再谈容器。
三、用 host.docker.internal 指向宿主机
Docker Desktop for Windows(以及较新版本的 Docker Engine)在容器内提供了特殊主机名 host.docker.internal,解析到从容器网络视角可路由到的宿主机地址。这是比手写宿主机局域网 IP 更稳的默认选择:升级 Docker 或切换 Wi‑Fi 后,仍可减少硬编码 IP 带来的维护成本。
将代理 URL 写成类似 http://host.docker.internal:7890 的形式,其中端口替换为你在 Windows 上为 Clash 配置的混合端口。若你的客户端把 HTTP 与 SOCKS 拆成两个端口,请分别对应到工具所支持的协议(例如 HTTPS_PROXY 常配 HTTP 代理协议 URL,具体以应用文档为准)。
host.docker.internal 并非在所有 Linux 裸机安装场景都默认存在;本文语境限定在 Windows 上的 Docker Desktop。若在纯 Linux 宿主机上部署,需改用宿主机桥接 IP 或文档推荐的主机名。
四、HTTP_PROXY、HTTPS_PROXY 与 Compose 写法
绝大多数命令行工具与语言生态认以下环境变量(大小写变体常见,建议同时设置大写与小写以兼容旧程序):HTTP_PROXY、HTTPS_PROXY,以及需要 SOCKS 时的 ALL_PROXY。在 docker run 中可使用 -e HTTP_PROXY=... 传入;在 Docker Compose 中可在 service.environment 下列出,或使用 env_file 统一维护。
示例(端口请替换为你的混合端口):
HTTP_PROXY=http://host.docker.internal:7890
HTTPS_PROXY=http://host.docker.internal:7890
NO_PROXY=localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
若只在构建镜像时需要代理,可使用 BuildKit 的构建参数(如 docker build --build-arg HTTP_PROXY=...)或在 Compose 的 build.args 中声明,避免把敏感地址固化进最终镜像层——具体以 Dockerfile 是否使用 ARG 为准。
五、NO_PROXY:内网、镜像与本地服务例外
NO_PROXY(或 no_proxy)用于列出不应走代理的主机名、域名或网段。把它配好,能避免「访问公司内网 Git 仍被送去境外节点」「拉取私有镜像仓库异常缓慢」等问题。常见需要直连接入的对象包括:localhost 与 127.0.0.1、RFC1918 私网段(如 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)、以及你内网 DNS 的域名后缀。
对于 Docker Hub 与国内镜像加速地址是否走代理,取决于你的网络环境与合规要求:若直连拉取稳定,可将相关域名或 IP 段加入 NO_PROXY;若必须通过代理访问外网 registry,则不要把目标 registry 主机名错误地写进 NO_PROXY。同一原则适用于 npm、PyPI 等企业私服:私网地址应直连,公共索引若需出境再加代理。
| 症状 | 优先核对 |
|---|---|
| 容器内 curl 外网仍超时 | 环境变量是否传入容器;host.docker.internal 是否解析;混合端口是否 Allow LAN;防火墙入站 |
| 内网或私服突然变慢 | NO_PROXY 是否漏掉域名后缀或网段;工具是否只认小写 no_proxy |
| 仅 build 失败,run 正常 | 构建阶段是否单独需要 --build-arg;多阶段 Dockerfile 是否在正确阶段注入 |
六、验证清单:curl 与一次性容器测试
按下列顺序做最小对照实验,能快速定位问题层级:
- 在 Windows 上用
curl.exe经-x指向混合端口访问 HTTPS,确认 Clash 本身可用。 - 运行临时容器(示例镜像可按你环境替换)并传入代理环境变量,在容器内执行
curl -v访问外网,观察是否经代理建立 CONNECT。 - 若失败,先在容器内
ping或getent hosts host.docker.internal(视基础镜像工具而定)确认主机名解析与路由。 - 再检查防火墙与监听地址,回到第二节重复验证。
建议把当前使用的混合端口号、NO_PROXY 列表、以及公司内网后缀记在团队 Wiki 模板中,新人拉 Compose 仓库时能直接复制,减少「我本机可以、CI 不行」的差分。
七、构建阶段、DNS 与 TUN 的补充说明
DNS:容器内域名解析路径由 Docker 的 DNS 配置决定;若出现「IP 能访问、域名不行」,除了代理变量,还要对照 Corefile / resolv.conf 是否与 Clash 的 fake-ip 策略冲突。这与 fake-ip 系列排障文一致,可按需交叉阅读站内 fake-ip 与 DNS 排查。
TUN 模式:当 Clash 在 Windows 上启用 TUN 全局接管时,部分流量路径会变化;若容器仍独立桥接,可能仍需要显式环境变量。若你观察到宿主机已全局代理而容器仍旧例外,请结合 TUN 与路由防火墙排查 先确认 Windows 侧无断网或环路,再回到 Compose 层。
与 WSL2 的区别:若你同时在 WSL2 与 Docker Desktop 上开发,两套环境对「宿主机地址」的取值方式不同;WSL2 常参考 /etc/resolv.conf 中的 nameserver,而 Docker 优先 host.docker.internal。不要混用教程里的 IP,以免升级系统后集体失效。
八、小结
在 Windows 上使用 Docker Desktop 时,Clash 能否为容器服务,取决于你是否把容器进程与宿主机上的混合端口用明确的方式连接起来:host.docker.internal 提供可达性,HTTP_PROXY / HTTPS_PROXY 提供语义,NO_PROXY 则守住内网与镜像仓库的例外边界。相比反复尝试换节点,先把「监听范围、防火墙、环境变量是否传入」对齐,排障会快一个数量级。
Clash 在规则分流与多平台客户端上的一致性,使它很适合作为开发机的统一出口;把 Docker 与浏览器放在同一套策略下管理,日常拉镜像、装依赖会稳定得多。若你尚未安装或希望使用维护活跃的客户端,可从本站获取安装包并按 配置文档 完成混合端口基础设置。