开发与 AI · Clash 技术博客

Docker 与 WSL2 怎么走 Clash 代理?镜像拉取超时与网络配置

docker pull、WSL2 下载与容器内请求由不同进程发起。根据报错位置检查宿主地址和对应代理设置,为构建或容器单独传入变量,并用 NO_PROXY 保留数据库与内部服务直连。

  • Docker
  • WSL2
  • 开发环境
本文目录

开发环境里最容易误配的,是把电脑上能用的代理地址直接复制到所有终端和容器。真正需要确认的是:报错由哪个进程发出,它能不能访问代理所在的宿主机。连接测试通过后再保存长期设置,也要给数据库等内部服务保留直连。

docker pull、WSL 下载与容器请求的代理设置

报错由哪个程序发起?

失败动作发起请求的程序
curl / apt / git 在 WSL 里超时WSL 发行版中的进程
docker pull 超时Docker Desktop 或 Docker Engine 守护进程
RUN apt-get 在 build 时超时BuildKit / 构建容器
启动后的应用请求失败运行中的容器

Windows 上的 Clash 监听 127.0.0.1,只保证 Windows 本机能访问。WSL2 默认运行在 NAT 虚拟网络里,容器也有独立的网络环境;它们访问 127.0.0.1 时通常连接的是自己,不是宿主机。

Windows、WSL2 与容器之间的代理路径
  1. Windows 上的 Clash监听局域网可达的 mixed-port
  2. WSL2使用宿主机地址访问该端口
  3. Docker 构建显式接收 HTTP_PROXY 和 HTTPS_PROXY
  4. 容器内工具再处理 Git、npm 或包管理器

Windows、WSL2 和各个容器访问 127.0.0.1 时,通常连接的是各自的网络环境。代理地址应填写当前环境能访问的宿主机地址。

让 WSL 能访问 Windows 的代理端口

先在 Clash 查看实际的 HTTP 或 mixed-port,常见示例是 7890,但你的客户端可能不同。WSL 使用宿主 IP 访问时,这个连接会被当作局域网连接,客户端需要允许 LAN 访问,并监听 WSL 能到达的地址。

允许 LAN 会扩大端口可达范围。只在可信的家庭或单位私有网络使用,并让 Windows 防火墙限制来源;不要把无认证代理暴露到公共 Wi-Fi 或公网。完成测试后若不再需要,可以关闭 LAN 访问。

默认 NAT 与镜像网络的宿主地址

默认 NAT 模式下,可以在 WSL 读取默认路由的下一跳,它通常就是 Windows 宿主在 WSL 虚拟网络里的地址。Windows 11 22H2 及后续版本启用 mirrored networking 后,WSL 可以直接通过 127.0.0.1 访问 Windows 服务。

WSL 默认 NAT 测试,7890 是待替换的 Clash 端口
HOST_IP=$(ip route show | grep -i default | awk '{ print $3 }')
CLASH_PORT=7890
echo "Windows host: $HOST_IP"
curl -I -x "http://${HOST_IP}:${CLASH_PORT}" https://example.com

这条 curl 得到 HTTP 响应后,才有必要设置 WSL 环境变量。若代理端口直接返回 Connection refused,问题在 Clash 监听、允许 LAN 或防火墙;若端口可达但外部请求 timeout,再检查节点和规则。

设置 WSL shell 的 HTTP_PROXY 与 HTTPS_PROXY

当前 WSL shell 临时生效,7890 是端口占位值
HOST_IP=$(ip route show | grep -i default | awk '{ print $3 }')
CLASH_PORT=7890
export HTTP_PROXY="http://${HOST_IP}:${CLASH_PORT}"
export HTTPS_PROXY="http://${HOST_IP}:${CLASH_PORT}"
export NO_PROXY="localhost,127.0.0.1,::1"
curl -I https://example.com

临时变量供当前终端启动的程序读取。用 git 或 curl 重做同一 HTTPS 请求,成功后再按 shell 类型写入自己的启动文件;curl 访问 HTTP 地址时读取小写 http_proxy,不能只靠 HTTP_PROXY。

apt 的 HTTP 传输读取小写 http_proxy、no_proxy,或自身的 Acquire::http::Proxy 设置;用 sudo 启动时还要核对环境是否保留。不要把上面的变量段当成所有工具通用的代理设置。

Windows 支持的 WSL 版本也可以在 .wslconfig 使用 autoProxy=true,让 WSL 导入 Windows 的 HTTP 代理信息。启用后要重启 WSL,并检查实际变量值。

NO_PROXY 应包含只在 WSL 内部提供的服务,避免访问 localhost 时绕到 Windows 代理。公司内部域名和私有网段是否加入,要按实际网络决定。

Docker Desktop 与独立 Engine 的代理入口

Docker Desktop 拉取镜像与 WSL shell 下载由不同进程发起。只在 WSL 中 export HTTP_PROXY,不会自动配置 Desktop 的镜像拉取。

打开 Docker Desktop 的 Settings,在 Resources / Proxies(标签可能随版本变化)填写宿主可用的 HTTP、HTTPS 代理,并应用设置。

页面分为 Docker Desktop proxy 和 Containers proxy 时,镜像拉取要检查 Containers proxy;只有 Containers proxy 未配置时,Docker Desktop proxy 才作为后备。改完后用 docker pull 验证。

Docker 官方文档明确说明,Desktop 不读取 daemon.json 里的守护进程代理配置。不要因为 WSL 终端已经能访问,就跳过 Docker Desktop 自己的代理设置。

若使用的是独立 Linux Docker Engine,而不是 Docker Desktop,才按 Engine 文档在 daemon.json 或 systemd 环境中设置守护进程代理,并重启 Docker 服务。先确认自己运行的形态,避免改了一个根本不被读取的文件。

为镜像构建和运行容器分别传入代理

Docker 的客户端配置可以为新容器和构建自动注入代理环境,也可以在单次命令里显式传入。构建时用 --build-arg,运行时用 --env;不要在 Dockerfile 里用 ENV 固化带凭据的代理地址,镜像历史和配置可能把它留下。

下面示例在含有 Dockerfile 的项目目录中执行,demo-app 是本次构建的镜像名,可按自己的项目替换。它不是独立连通测试;代理端口是否可达,先用前文的 curl 检查。

Docker Desktop 现有项目示例,7890 是待替换的 Clash 端口
CLASH_PROXY=http://host.docker.internal:7890

docker build \
  --build-arg HTTP_PROXY="$CLASH_PROXY" \
  --build-arg HTTPS_PROXY="$CLASH_PROXY" \
  -t demo-app .

docker run --rm \
  --env HTTP_PROXY="$CLASH_PROXY" \
  --env HTTPS_PROXY="$CLASH_PROXY" \
  --env NO_PROXY="localhost,127.0.0.1" \
  demo-app

Docker Desktop 通常提供 host.docker.internal 指向宿主机。原生 Linux Engine 是否可用取决于环境,需要用明确的宿主网关或额外 host-gateway 配置。命令执行前,用容器内的 curl 或应用日志验证这个主机名和端口确实可达。

NO_PROXY:让数据库与内部服务保持直连

数据库名、Compose 服务名、localhost 和内部网段通常不应交给外部代理。把实际内部域名加入 NO_PROXY,避免应用访问 db:5432、redis:6379 时先转到 Windows 代理。不同工具对通配符和 CIDR 的支持不同,配置后要在目标进程里打印变量并发起实际请求。

代理地址若含用户名或密码,不要写进公开的 compose.yaml、Dockerfile 或镜像。使用本地环境文件或项目的 secret 管理方式,并确保日志不会把完整 URL 打出来。

按实际使用完成四次验证

  • WSL 中 curl 通过 Windows Clash 得到响应
  • docker pull 可以拉取一个小镜像
  • docker build 的网络步骤不再超时
  • 运行容器既能访问外网,也能直连内部服务

参考资料