本文目录
开发环境里最容易误配的,是把电脑上能用的代理地址直接复制到所有终端和容器。真正需要确认的是:报错由哪个进程发出,它能不能访问代理所在的宿主机。连接测试通过后再保存长期设置,也要给数据库等内部服务保留直连。
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 上的 Clash监听局域网可达的 mixed-port
- WSL2使用宿主机地址访问该端口
- Docker 构建显式接收 HTTP_PROXY 和 HTTPS_PROXY
- 容器内工具再处理 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 服务。
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
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 检查。
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-appDocker 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 的网络步骤不再超时
- 运行容器既能访问外网,也能直连内部服务
