一、為什麼瀏覽器可走代理,容器卻像直連
在 Windows 上,Clash 透過系統代理或 TUN 接管瀏覽器流量時,使用者很容易誤以為「整臺電腦都已經走代理」。然而 Docker Desktop 啟動的 Linux 容器擁有獨立的網路命名空間:容器內的 127.0.0.1 指向容器自己,而不是宿主機上正在監聽混合埠的 Clash。除非應用程式主動讀取代理環境變數,或你使用 network_mode: host(在 Linux 宿主機上較常見;Windows 上 Docker 語意不同,不應假設與本機文件相同),否則預設情況下容器不會自動繼承你在 Windows 裡設好的「系統代理」。
因此,典型現象是:Edge/Chrome 可開啟海外網站,但同一臺機器上 docker run 內的 curl、apt、pip 或 Compose 服務仍直連或逾時。這與訂閱是否過期未必相關,而是流量沒有被送到宿主機上的 Clash 監聽埠。接下來先把「位址寫對」與「Clash 願意接受從 Docker 網橋過來的連入」兩件事拆開處理。
curl -v http://127.0.0.1:(你的混合埠) 若顯示連線被拒,而 Windows 上同一埠正常,代表問題在命名空間而非節點品質;請改測 host.docker.internal(見下一節)。
二、host.docker.internal 與宿主機位址對齊
Docker Desktop for Windows 在 Linux 容器內提供特殊主機名 host.docker.internal,用來解析到宿主機(對容器而言可路由到的位址)。將代理寫成 http://host.docker.internal:7890(請替換成你實際的 HTTP/混合埠)時,應用程式會向宿主機發起連線,再由 Clash 承接並依規則分流。
若你的客戶端同時暴露 SOCKS,也可使用 all_proxy=socks5h://host.docker.internal:(socks 埠);socks5h 讓遠端解析在代理側完成,較符合 Clash 處理網域規則的預期。純 HTTP 代理情境下,維持 http:// 前綴與正確埠號即可。建議在容器內用 getent hosts host.docker.internal 或 ping -c1 host.docker.internal(若映像允許)確認名稱可解析,再用 curl -v --proxy http://host.docker.internal:埠 https://www.example.com 做端到端驗證。
host.docker.internal 不存在,請查閱當前 Docker 版本文件,或改以宿主機在 docker0/Hyper-V 網段上的實際 IP(較不友善但可行),並同步更新防火牆規則。
三、Clash 監聽混合埠與「允許區域網路」
容器要連到宿主機上的 Clash,本質上是從 Docker 網橋網段連入 Windows 的某個 TCP 埠。若 Clash 僅監聽 127.0.0.1,而沒有對 Docker 來源開放,連線仍會失敗。多數圖形客戶端提供「允許區域網路連線」或「Allow LAN」類選項,效果接近讓混合埠綁在 0.0.0.0 或額外接受區網介面連入。請在客戶端核對 Mihomo/核心日誌與 Windows 資源監視器,確認目標埠確實在非僅 loopback 上監聽。
建議檢查項
- 混合埠、HTTP 埠、SOCKS 埠數字與你在容器內設定的
HTTP_PROXY完全一致。 - Windows Defender 防火牆是否允許 Clash 主程式或核心行程在私人網路上接受連入;細節可對照 《Clash Windows 11 混合埠與區域網路共享》 的實測步驟。
- 若你啟用 TUN 模式,路由與虛擬介面互動較複雜,可搭配 《Clash TUN 與 Windows 路由、防火牆排查》 確認沒有與 Docker 網路衝突。
先確保「TCP 能打到 Clash 監聽埠」,再談規則與節點,可避免把系統問題誤判成訂閱故障。
四、HTTP_PROXY、HTTPS_PROXY 與大小寫變體
容器內常見寫法為設定 HTTP_PROXY、HTTPS_PROXY,以及涵蓋兩者的 ALL_PROXY。許多執行環境同時接受小寫 http_proxy/https_proxy;為相容不同工具,建議兩套並列寫成相同值,避免只有 Go/部分程式讀到大寫、Python 預設讀小寫之類的落差。
範例(混合埠為 7890,請依實際修改):
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,.local
若映像內程式使用 SOCKS,請改用對應配置式;重點是主機名一律指向宿主機可解析的位址,而不是 127.0.0.1。
五、NO_PROXY:內網、映像倉庫與 Docker 內建 DNS
把容器內所有流量都塞進 Clash,常會踩到兩類雷:私有映像倉庫、公司內網 API 與 Kubernetes/Docker 內部服務名。此時必須設定 NO_PROXY(或 no_proxy),讓這些目標不經過 HTTP 代理。
建議列入的型別
- RFC1918 私網位址:
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16(依你環境精簡)。 - 本機與 loopback:
localhost、127.0.0.1、::1。 - 內部網域後綴:例如
.corp.example.com、.internal;請依實際 DNS 後綴調整。 - Docker 內建 DNS 名稱:在 Compose 堆疊中,服務互連常用容器名、
*.docker.internal類名稱;若誤走代理,可能出現「解析不到」或 TLS 對錯主機。可將常用後綴或完整主機名加入NO_PROXY。
拉映像時若需走代理加速,請不要把 registry-1.docker.io 無條件塞進 NO_PROXY;反之,若內網 Registry 與外網同名衝突,請用更精確的網域清單或拆分環境。此段需依你的實際倉庫位址微調,沒有一組適用全世界的固定字串。
六、docker run、Compose 與映像建置階段
對單次容器,可在 docker run 使用 -e HTTP_PROXY=... 傳入;或在 Compose 的 environment/env_file 區塊統一宣告,讓多個服務共用。若只有某個服務需要代理,請避免把變數寫在全域而讓資料庫連線也誤走代理。
docker build 預設不會自動帶入宿主機代理;若 Dockerfile 內需要 apt-get、pip 下載,請在 docker build 時加上 --build-arg HTTP_PROXY=... 等,並在 Dockerfile 以 ARG 接收。否則建置階段仍可能直連,與執行階段行為不一致。
Docker Desktop 設定頁亦提供「Proxies」相關選項(版本而異),可作為引擎層預設補充,但仍建議你在 Compose 中顯式寫出與 Clash 一致的位址,方便版本控制與除錯。需要查核心與規則語法時,可一併參考 本站設定與規則文件。
七、容器內 DNS 與 Fake-IP 的注意點
當 Clash 使用 Fake-IP 時,解析行為與一般公共 DNS 不同。容器內若自行用 dig 對外查詢,看到的 IP 可能與經過 Clash 核心的路徑不一致,進而出現「偶發連線」或「HTTPS 憑證與網域不符」等現象。實務上仍建議先確認應用程式是否把 TLS 與 HTTP 都交給代理,並避免在容器內繞過代理做與規則無關的獨立解析。
若你已能透過 curl --proxy 存取外網,但特定語言執行時仍失敗,請檢查該執行環境是否忽略環境變數(例如部分 Node/Java 需額外 JVM 參數)。這類問題與 Docker DNS(127.0.0.11)無衝突時,多半是程式行為而非 Clash 規則本身。
八、與 WSL2 場景的差異(為何另成一篇)
本站另有一篇 《WSL2 走不通 Windows 上的 Clash?檢查 localhost 轉發與 DNS 逐步排查》,處理的是子系統終端機與 Windows 宿主機之間的 localhost 語意、resolv.conf 與路由。本文則聚焦 Docker Desktop 容器網路、host.docker.internal、HTTP_PROXY/HTTPS_PROXY/NO_PROXY 與映像建置階段。
兩者都可能需要「允許區域網路」與防火牆放行,但故障點與檢查命令不同:WSL2 常用 ip route 找宿主機 IP;Docker 則優先依賴 host.docker.internal 與 Compose 網路名稱。請依你的實際工作負載選對文章,避免混用指令造成誤判。
九、可復現檢查清單
| 現象 | 優先檢查項 |
|---|---|
容器內 127.0.0.1:混合埠 失敗,Windows 正常 |
改用 host.docker.internal;確認非 loopback 監聽與防火牆 |
| 可拉映像但 apt/pip 仍慢或失敗 | build 階段 --build-arg;執行階段環境變數是否帶入 |
| 內網 Registry 或 API 突然連不上 | NO_PROXY 是否涵蓋正確網域/私網 CIDR |
| Compose 服務彼此連線異常 | 服務名是否被誤送代理;調整 NO_PROXY 或網路別名 |
建議固定順序:名稱解析 host.docker.internal → TCP 到混合埠 → HTTPS 端到端 → 再調 NO_PROXY。每步通過再進下一步,可快速縮小範圍。
十、小結
在 Windows 上使用 Docker Desktop 時,要讓容器流量走宿主機上的 Clash,核心是把代理位址從 127.0.0.1 改寫成可達宿主機的名稱或 IP(首選 host.docker.internal),並為 HTTP_PROXY、HTTPS_PROXY 與 NO_PROXY 建立一致、可維護的約定。搭配「允許區域網路」與防火牆放行,才能把容器網橋到宿主機混合埠這條路真正打通。
與僅在瀏覽器裡上網相比,開發與維運場景更要求可重現:同一份 Compose 在同事電腦上也應能依環境變數對齊代理。Clash 在規則與核心上的彈性,能讓宿主機與容器共用同一套出口策略,只要網路語意先對齊,後續節點與規則調校會輕鬆許多。
若你尚未安裝 Windows 客戶端,或希望取得與本站文件一致的安裝路徑與安全預設,可先前往下載頁取得套件與說明,再依本文檢查清單自測混合埠與容器代理。