为什么终端与 Docker 常常不吃系统代理
在 macOS 上打开「自动代理配置」或在 Linux 桌面设置里填 HTTP 代理,Safari、Chrome 往往能跟着走;但你在 终端里敲的 curl、wget、git、npm、pip,默认并不会自动继承这些设置。很多工具只认环境变量(如 HTTPS_PROXY)或自己的配置文件,和「系统代理」是两条平行世界。于是出现经典错觉:浏览器一切正常,命令行却直连超时——不是 Clash 坏了,而是流量根本没进 Clash 的入站端口。
Docker 更复杂一层:docker pull 与 docker build 里执行的 RUN apt-get,往往跑在容器网络命名空间里,127.0.0.1 指向的是容器自己,不是宿主机上监听 mixed-port 的 Clash。要让镜像构建与镜像拉取走代理,要么把代理地址写成「从容器看得见的宿主地址」,要么给 Docker daemon 配环境变量,要么在 docker build 时注入 --build-arg。下文按「先定端口与协议 → 再写环境变量 → 再对齐 Docker 视角」的顺序,把这几件事一次对齐。
port(HTTP)与 socks-port,也可以不用 mixed-port,但单一 mixed-port对复制粘贴最省事。
Clash 侧:mixed-port、独立端口与 allow-lan
mixed-port 的含义是:在同一个 TCP 端口上同时接受 HTTP 代理 与 SOCKS5 连接(具体探测方式由协议握手决定)。这样你在终端里可以把 HTTP_PROXY 与 ALL_PROXY 都指向同一个 http://127.0.0.1:7890 或 socks5h://127.0.0.1:7890,减少「HTTP 走 7890、SOCKS 走 7891」的记忆负担。若配置里仍使用传统的 port + socks-port,把下面示例里的端口号改成你实际值即可。
只有本机终端用时,监听 127.0.0.1 即可。若你希望局域网内另一台设备或虚拟机 / WSL / 容器通过宿主机 IP 访问 Clash 入站,需要在配置中允许外部连接,并关注防火墙。常见键名包括 allow-lan: true 与 bind-address: '*' 或指定网卡地址;不同发行版界面用词不同,请以你客户端文档为准。更多分流与规则背景可对照 规则分流最佳实践。
mixed-port: 7890
allow-lan: true
bind-address: '*'
生产环境把 bind-address 暴露到局域网前,请确认你理解内网访问风险:同一 Wi‑Fi 下的其他设备也可能把流量送进你的 Clash。家庭实验与开发机常见,公共网络则应保持默认仅本机。
终端代理:HTTP_PROXY、ALL_PROXY 与 NO_PROXY
下面是一段在 bash/zsh 中可直接改端口复用的模板。核心是三件事:HTTP_PROXY/HTTPS_PROXY 给走 HTTP CONNECT 的工具;ALL_PROXY 给认「全协议代理」的程序;NO_PROXY 列出绝对不要走代理的主机与网段,避免内网、注册表、公司 Git 被误送出境。
export HTTP_PROXY="http://127.0.0.1:7890"
export HTTPS_PROXY="http://127.0.0.1:7890"
export ALL_PROXY="socks5h://127.0.0.1:7890"
export NO_PROXY="localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16"
socks5h:// 中的 h 表示把域名解析也交给代理侧(类似 curl 的远程解析)。若你写成 socks5://,部分工具会在本地解析域名,遇到污染或 split-DNS 时会出现「解析对了但连不上」的假像。NO_PROXY 的具体列表请按你的内网段裁剪:例如公司 Git 在 git.corp.example,应追加该主机名或后缀,否则 git clone 会无故变慢或失败。
想「临时开代理」时可在命令前加环境变量,只对单条命令生效;想长期生效则写入 ~/.zshrc 或 ~/.bashrc,并习惯配一对开关函数,避免全天误代理。若你使用 fish、PowerShell,变量名相同但语法不同,需要按 shell 文档改写。
git、语言包管理器与 curl 的注意点
Git 除环境变量外,还可显式设置 http.proxy / https.proxy,有时比依赖 ALL_PROXY 更直观:git config --global http.proxy http://127.0.0.1:7890。若某些远程必须直连,可用 git config http.proxy 按仓库覆盖,或依赖 NO_PROXY。SSH 协议([email protected]:)不走 HTTP 代理,需改用 HTTPS 远程或配置 ProxyCommand,这与本文 HTTP/SOCKS 入站是不同话题。
curl -I https://example.com 会读 HTTPS_PROXY;若你测试 Clash 是否工作,优先对「已知会走代理规则的目标」做请求,并在 Clash 连接日志里看到对应连接。若握手失败或证书报错,分层思路可参考 从日志读懂 timeout 与 TLS。
npm、yarn、pnpm 通常尊重 HTTP_PROXY/HTTPS_PROXY;部分工具还有自己的 proxy 字段。若你只开了 ALL_PROXY 而某 CLI 仍直连,优先补 HTTP_PROXY,再查该工具文档是否忽略标准变量。
Docker 里「本机」是谁:host.docker.internal 与网桥地址
在 Docker Desktop for Mac 上,容器访问宿主机服务推荐使用特殊主机名 host.docker.internal(Docker 会解析到宿主)。因此容器内的 HTTP_PROXY 可写作 http://host.docker.internal:7890,而不是 127.0.0.1。在纯 Linux 宿主机上,常见替代是默认网桥网关 172.17.0.1,或你 docker0 的实际地址;请以 ip addr show docker0 与路由为准,不同发行版可能略有差异。
WSL2 用户常遇到「Windows 里 Clash 监听 7890,Linux 发行版里要填 Windows 宿主 IP」的情况:需要查 WSL 文档中的 nameserver 或 ip route 默认网关,把代理指到 Windows 侧地址与端口,而不是 WSL 里的 127.0.0.1。此类环境变量同样建议配合 NO_PROXY,避免访问局域网注册表或内部镜像源时绕远路。
docker pull / docker build:daemon、build-arg 与配置文件
docker pull 由 Docker daemon 发起,环境变量要设在守护进程一侧,而不是你当前 shell。常见做法:在 systemd 的 docker.service drop-in 里加 Environment=HTTP_PROXY=...,或使用 /etc/systemd/system/docker.service.d/http-proxy.conf,然后 systemctl daemon-reload && systemctl restart docker。macOS 上 Docker Desktop 提供图形界面的代理设置,等价于写进 daemon 环境。
docker build 中 Dockerfile 的 RUN 指令运行在中间容器里,默认不会继承你 shell 里的 HTTP_PROXY。推荐用构建参数注入:
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG ALL_PROXY
ARG NO_PROXY
ENV HTTP_PROXY=$HTTP_PROXY HTTPS_PROXY=$HTTPS_PROXY \
ALL_PROXY=$ALL_PROXY NO_PROXY=$NO_PROXY
构建命令示例:docker build --build-arg HTTP_PROXY=http://host.docker.internal:7890 --build-arg HTTPS_PROXY=http://host.docker.internal:7890 .。构建结束后若不希望镜像层里长期保留代理环境变量,可在后续 stage 用多阶段构建丢弃,或在一层 RUN 末尾 unset(注意层缓存行为)。用户级配置亦可写入 ~/.docker/config.json 的 proxies 字段,对不同守护进程与客户端版本行为略有差异,升级 Docker 后若代理失效,先核对官方 Release Note。
SOCKS5 与 HTTP 代理在环境变量里怎么写
HTTP_PROXY 适合大量基于 HTTP CONNECT 的 HTTPS 流量;ALL_PROXY 常配 SOCKS5,以便某些工具统一走 SOCKS。Clash 的 mixed-port 让你二者共端口,但 URL scheme 仍要选对:http:// 与 socks5h:// 不能混用概念。若某工具只支持 HTTP 代理,却错误填了 SOCKS URL,会表现为立即拒绝或协议错误。
不建议在生产脚本里写死账号密码进 URL;若节点需要认证,优先使用支持认证注入的客户端或拆分密钥管理。对仅 ICMP/UDP 的特殊需求,HTTP/SOCKS 入站无能为力,需要回到 TUN 或应用自身设置。可选客户端与场景对照见 如何选择适合自己的 Clash 客户端。
与 TUN 模式对照:何时仍要开透明代理
显式 终端代理 的优势是可预测:哪些进程走代理由环境变量与工具行为决定,便于在 CI、脚本、容器里复现。缺点是:不尊重环境变量的程序仍会直连;多语言、多 shell、多服务各自配置,维护成本上升。TUN 模式在系统层接管路由,浏览器与多数 TCP 流量更「一体」,但可能与 VPN、公司零信任客户端、虚拟机路由互相干扰。Mac 上授权与冲突可对照 macOS TUN 与系统代理冲突;原理层阅读 TUN 模式深度解析。
实务上常见组合是:日常图形界面开 TUN 或系统代理;开发与构建机用 mixed-port + 环境变量;Docker 与远程 CI 单独一套 NO_PROXY。不要把两套方案混在排障时:先定「这条连接期望从哪进 Clash」,再看规则与日志。
排障:连不上、证书错、内网被误代理
- 连接被拒绝:核对 Clash 是否监听预期端口、客户端是否启用入站、以及防火墙是否放行。
- 容器仍直连:检查代理地址是否仍写
127.0.0.1;改为host.docker.internal或网桥网关。 - 内网变慢:扩充
NO_PROXY,把公司域名、私有仓库、Kubernetes API 地址纳入直连列表。 - 规则不命中:在日志中确认域名与策略,必要时调整规则顺序,参见 规则分流最佳实践。
若你对 DNS、fake-ip 或嗅探仍有疑问,可在 常见问题 中查阅 DNS 相关条目,再回到本文核对「环境变量是否生效」这一层。
结语:把可复制模板收进你的 shell 配置
把 Clash mixed-port、SOCKS5 与 HTTP 代理写进同一段环境变量模板,再配合精心维护的 NO_PROXY,你在 macOS、Linux 与 Docker 之间切换时,不必每次重新猜「127.0.0.1 到底是谁」。这与本站已发布的 TUN、系统代理、Ubuntu systemd 等文章形成互补:透明代理解决「全局一致性」,本文解决「终端与容器可复制的显式入口」。
相比依赖零散博文片段,把端口、协议、变量名固定在团队文档里,排障时只需对照连接日志与 docker info 环境,能显著减少无效重装与误改订阅。成熟图形客户端在入站开关、规则编辑与日志可读性上往往更省心;若你希望同一套策略在桌面与命令行之间少踩坑,选一个维护积极的发行版长期跟随即可。
相比其它同类工具,把策略编辑与连接日志放在手边、用现代内核承载分流规则,日常验证「终端是否真的进了 Clash」会轻松很多。
→ 立即免费下载 Clash,开启流畅上网新体验,在图形界面里对齐 mixed-port 与规则,再把本文模板粘贴进终端与构建流水线。