這篇教學要解決什麼:Docker Hub 為什麼需要 Clash TUN 透明代理
在 Linux 主機、家用伺服器或企業網路中執行 docker pull 時,最常見的問題不是 Docker Engine 本身故障,而是Docker Daemon 的網路路徑與桌面應用程式不同。你可能在瀏覽器裡可以開啟 Docker Hub,甚至已經把 Clash Verge Rev 的系統代理打開,但執行 docker pull nginx 仍然出現 i/o timeout、TLS handshake timeout、context deadline exceeded 或無法解析 Registry 網域的錯誤。
原因在於 Docker CLI 通常只是向背景執行的 Docker Engine 發送請求,真正連線到 registry-1.docker.io、auth.docker.io、production.cloudflare.docker.com 等端點的是 dockerd。這個背景服務可能由 systemd 啟動,沒有繼承你目前 Shell 的 HTTP_PROXY 或 HTTPS_PROXY;即使設定了環境變數,Docker Registry 在重新導向、驗證與映像檔分層下載時,也可能使用另一組網域。單獨設定一個代理埠,並不等於所有 Docker 流量都會穩定進入 Clash。
本篇以支援 Mihomo/Clash.Meta 核心的桌面用戶端為例,說明如何用TUN 模式接管主機流量,再透過 DNS、規則集與 Docker Engine 設定建立可觀察、可回復的代理路徑。重點不是把所有流量永久送進代理,而是先確認封包是否進入 Clash,再依 Docker Hub 的實際連線網域進行分流。企業環境還需要考慮公司 VPN、端點防護、內部 Registry 與憑證政策,不能只複製一段 YAML 就期待所有主機都得到相同結果。
代理工具的使用仍應符合所在地法規、公司資訊安全規範,以及 Docker Hub、映像檔供應商與訂閱服務的使用條款。以下內容用於一般網路診斷、容器部署與合法的連線管理,不建議繞過企業審計或未經授權的網路管制。
先理解 Docker pull 的實際連線路徑
執行 docker pull alpine 時,Docker 不一定只連線到一個固定網址。Docker Engine 通常會先向 Registry 取得 API 回應,再向驗證服務索取 Token,接著依回應中的摘要與下載位置抓取映像檔 layer。這幾個階段可能對應不同主機,因此只把 docker.io 加入規則,並不一定能涵蓋完整流程。
| 階段 | 常見目的地 | 排錯時要觀察的現象 |
|---|---|---|
| Registry API | registry-1.docker.io、index.docker.io |
無法取得映像檔清單、回傳連線逾時或 5xx |
| 身分驗證 | auth.docker.io |
出現 unauthorized、Token 取得失敗或登入後仍無法拉取 |
| Layer 下載 | Docker CDN 或雲端儲存相關網域 | 前面步驟成功,但某一層下載停住、速度忽快忽慢 |
| DNS 查詢 | 系統 DNS、Clash DNS 或企業內部解析器 | 網域偶發解析失敗、解析到不可達的位址或等待時間過長 |
因此,排錯時不要只看 Docker CLI 顯示的最後一行錯誤。先在 Clash 的連線紀錄中搜尋 docker、registry 或完整網域,確認請求是否出現、使用了哪個策略,以及遠端位址是否在下載中途改變。如果完全找不到相關紀錄,問題多半在流量沒有進入 Clash,而不是規則名稱寫錯。
也要分清楚Docker CLI、Docker Engine 與容器內程序這三個層次。CLI 是你輸入命令的客戶端;Engine 負責向 Registry 發出 pull 請求;容器啟動後執行的 apt、npm、pip 或應用程式,又是另一批連線。TUN 可以在主機層接管更多流量,但容器網路、Docker 自訂 bridge、主機防火牆與路由策略仍可能影響最後結果。
TUN、系統代理與 Docker Engine 代理的差異
在這個場景裡,三種方法各自解決不同問題。系統代理主要讓遵循作業系統設定的 HTTP/HTTPS 應用程式使用 Clash 的 mixed port;Docker Engine 代理則明確告訴 dockerd 發出外部請求時要使用哪個 HTTP 代理;TUN 模式則在虛擬網路介面與路由層接管更多不讀取代理環境變數的連線。
| 方案 | 主要優點 | 限制與風險 | 適合的使用時機 |
|---|---|---|---|
| 系統 Proxy | 設定簡單,對瀏覽器與一般 GUI 工具有效 | dockerd、某些 CLI 或背景服務可能完全不讀取 | 先確認 Clash 基本代理是否正常 |
| Docker Engine Proxy | 責任範圍清楚,適合只代理 Docker Daemon | 需要處理 systemd 環境、代理位址與服務重啟 | 伺服器只需要固定拉取外部映像檔 |
| Clash TUN | 可涵蓋不支援環境變數的程序與較底層的連線 | 可能與 VPN、企業端點安全工具、容器路由互相影響 | 連線沒有出現在 mixed port,或需要驗證透明接管 |
| TUN 加 Engine Proxy | 可分層處理主機與 Docker 服務,便於建立備援 | 路徑重複時可能產生迴圈、雙重代理或難以判讀的紀錄 | 經過測試後,依企業政策選擇一條主要路徑 |
實務上不建議一開始同時打開所有接管功能。先確認 Clash 的 mixed port 可以正常代理,再單獨啟用 TUN,最後才測試 Docker Engine。若 TUN 與 Docker Engine Proxy 同時啟用,必須確認 Docker 所指向的代理位址是主機可達的監聽位址,而不是只在 TUN 介面上可見的特殊位址,並留意 Clash 是否把自身的代理端點再次送回 TUN。
docker pull,比同時替換訂閱、規則集與網路模式更容易找出根因。
動手設定:先完成 Clash TUN、DNS 與規則
以下流程適用於 Clash Verge、Clash Verge Rev 或其他使用 Mihomo 核心的用戶端。不同版本的介面名稱可能是「TUN 模式」、「服務模式」、「核心設定」或「網路接管」,但判斷原則相同:確認核心啟動、虛擬介面建立、DNS 行為可預期,並讓 Docker Hub 相關目的地套用正確策略。
- 先備份目前設定檔。保留原始 YAML 或匯出目前設定,尤其記下 DNS、fake-ip、mixed port、tun 與 rules 部分。若企業主機原本依賴內部 DNS,不要直接覆蓋整份設定。
- 確認代理策略組可用。先用一般瀏覽器或
curl測試一個確定可達的 HTTPS 網站,再在 Clash 介面確認節點沒有全部離線。Docker 拉取大型 layer 需要長時間連線,不能只用瞬間延遲判斷節點品質。 - 啟用 TUN 與必要權限。部分 Linux 或桌面環境需要服務模式、管理員權限或額外的虛擬網路元件。啟用後確認系統出現 TUN 介面,並檢查預設路由是否被修改。若主機同時使用公司 VPN,先記錄原本的路由表。
- 設定 DNS 行為。Docker Registry 的域名解析必須穩定。若使用 fake-ip,請確認 Docker、內部服務與需要真實 IP 的網域已加入排除清單;若企業 DNS 只能解析內部域名,則應保留內部 DNS 的解析路徑,不要為了代理外部域名而讓所有內部名稱失效。
- 加入 Docker Hub 相關規則。將 Registry、驗證服務與連線紀錄中實際出現的 CDN 網域導向同一個代理策略組。規則順序要放在過寬的直連規則或 GEOIP 規則之前,否則明確網域規則可能永遠不會被命中。
- 重新載入核心並觀察連線。不要只看 TUN 開關顯示為啟用。執行測試後,在連線列表確認目的地、策略、DNS 結果與流量方向;如果只看到 DNS 請求卻看不到 HTTPS,代表可能仍有路由、憑證或服務權限問題。
設定片段的寫法會因核心版本與既有設定而不同,請不要把網路上完整 YAML 直接覆蓋到正在使用的訂閱設定。概念上需要檢查的項目包括 mixed-port、tun、dns、fake-ip-filter、rules 與策略組名稱。若你使用遠端訂閱,更新訂閱後還要確認自訂規則是否仍然存在;有些訂閱服務會在更新時重建完整設定,導致手動加入的 Docker 規則消失。
規則不宜只寫一個模糊的 DOMAIN-SUFFIX,docker.io 就結束。它可以作為起點,但實際上還要依連線紀錄補足驗證與 layer 下載所使用的端點。更穩妥的做法是先用測試映像觸發完整流程,再針對「確實由 Docker Hub 使用」的域名加入規則,而不是把所有陌生 CDN 一律送到代理。企業環境尤其要避免把內部 Registry、內部鏡像站或私有雲端儲存誤套用外部出口。
Docker Engine 整合:systemd 代理與 TUN 的取捨
如果 TUN 已經啟用,但 docker pull 的連線仍沒有出現在 Clash,下一步要檢查 Docker Engine 的服務環境。先查看 Docker 是否由 systemd 管理,以及服務實際使用的設定。常見診斷指令如下:
systemctl status docker
systemctl show --property=Environment docker
docker info
ip route
resolvectl status
若企業政策允許,而且你只希望 Docker Daemon 使用代理,可以為 Docker 服務建立 drop-in 設定,讓 dockerd 讀取代理環境變數。代理位址必須是 Docker 主機能連到的監聽端點;若 Clash 只監聽 127.0.0.1,某些隔離環境、虛擬機或容器網路就可能無法使用。不要直接把包含帳號密碼的代理 URL 貼到公開文件,因為 systemd 設定檔與診斷輸出可能被其他管理者讀取。
sudo systemctl edit docker
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,.local,registry.internal.example"
sudo systemctl daemon-reload
sudo systemctl restart docker
上面的連接埠只是示例,請替換為你的 Clash mixed port 或企業核准的代理端點。NO_PROXY 也不能照抄:它應該包含本機、Docker 內部位址、公司內部 Registry 與不應離開企業網路的服務。若把過寬的網域放入 NO_PROXY,可能讓 Docker Hub 請求繞過代理;若完全不設定,又可能讓內部 Registry 被送到外部節點,造成認證失敗或合規風險。
修改後先檢查服務是否真的收到新環境變數,再進行拉取測試。若 Docker Engine Proxy 與 TUN 同時開啟,連線可能會經過「dockerd → Clash mixed port → TUN → 代理節點」的多層路徑。這不一定錯,但遇到重複代理、TLS 錯誤或連線紀錄出現本機代理埠互相呼叫時,應暫時關閉其中一種方式,先建立單一路徑再逐步加回功能。
還要注意容器內的網路與 Docker pull 並不是同一件事。docker pull 主要由 Engine 發出;容器啟動後執行套件更新,則可能需要在容器環境設定 HTTP_PROXY、HTTPS_PROXY 與 NO_PROXY,或使用 Docker 的全域 daemon 設定。不要因為映像檔成功下載,就推論容器內的應用程式也能連到外部服務。
逐層驗證:從 DNS 到映像檔 layer 的排錯順序
建議採用由近到遠的測試順序,不要一開始就拉取數 GB 的大型映像檔。先確認本機能解析名稱,再確認 HTTPS 握手,接著確認 Docker Registry API,最後才測試實際映像檔下載。這樣可以把 DNS、代理、認證與 layer CDN 問題分開。
- 確認 DNS:使用
getent hosts registry-1.docker.io或系統提供的 DNS 查詢工具,觀察回應是否穩定。若不同時間解析結果差異很大,先檢查 Clash DNS、企業 DNS 與 fake-ip 排除設定。 - 確認 HTTPS:以不暴露私密 Token 的方式使用
curl -I https://registry-1.docker.io/v2/,預期可能得到需要驗證的 HTTP 回應,但不應長時間無回應。若 Clash 有連線紀錄而 curl 仍失敗,再查看節點的 TLS 或 SNI 相容性。 - 確認 Docker Engine:執行小型、公開且常見的測試映像,例如
docker pull hello-world。觀察每個 layer 是否開始下載,以及 Clash 連線列表是否同步出現 Registry 與驗證網域。 - 確認長連線穩定性:如果小映像成功、大映像中途停住,問題可能在節點頻寬、CDN 路由、連線重用或企業防火牆,而不一定是規則錯誤。可改用另一個策略組做對照,但要保留同一套 DNS 與 TUN 條件。
- 確認重啟後狀態:重新啟動 Clash、Docker Engine 或整台主機後再次測試。許多「偶爾成功」其實是服務啟動順序不固定,導致 Docker 在 Clash 尚未建立監聽埠或 TUN 路由前就開始工作。
若錯誤訊息是 no basic auth credentials,優先檢查 Docker Registry 登入資訊,而不是立刻改 TUN。若是 lookup ... server misbehaving,先處理 DNS;若是 connection refused,檢查代理監聽位址與連接埠;若是 context deadline exceeded,則要在 Clash 連線紀錄中區分「沒有進入核心」與「已進入但遠端節點逾時」。相同的錯誤文字可能由完全不同的網路層造成。
企業網路還可能有 TLS Inspection、HTTP 代理強制認證、出口防火牆或容器主機不允許建立 TUN 介面等限制。這類環境不應自行匯入未知 CA 憑證或關閉安全檢查;應向網路管理者確認核准的 Registry、代理端點與憑證鏈。如果公司已有內部 Docker Registry 或鏡像快取,優先使用官方核准的快取,通常比讓每台主機直接連外更容易稽核與維護。
常見問題:Docker Hub 與 Clash TUN 設定疑難
Docker Engine 已設定 HTTPS_PROXY,還需要開啟 TUN 嗎?
不一定。若 Docker Engine、systemd 環境與代理端點都設定正確,而且所有 Registry、驗證與下載網域都能穩定通過代理,單獨使用 Engine Proxy 通常已足夠。TUN 的價值在於補足不讀取環境變數的程序、提供主機層的透明接管,以及協助確認某些背景連線是否繞過代理。建議先用單一方法建立可重現的結果,再視需要啟用 TUN,而不是把兩種接管方式當成必須同時開啟的功能。
為什麼加入 docker.io 規則後,Docker pull 還是卡住?
因為映像檔下載可能涉及 Registry API、Token 驗證與 CDN layer 網域。docker.io 只代表主要服務名稱,不保證所有重新導向目的地都會匹配同一條規則。請在 Clash 連線列表中觀察完整域名,將確認屬於 Docker Hub 流程的端點加入適當策略,並檢查規則順序是否被更早的直連、GEOIP 或 FINAL 規則攔截。
Docker pull 成功,但容器內的 apt 或 npm 仍然無法連線,怎麼辦?
這是兩個不同層次的連線。pull 由 Docker Engine 負責,容器內的套件管理器則使用容器自己的網路命名空間與 DNS。你可能需要在 Docker daemon、Compose 服務或容器環境設定代理,也要把企業內部網域加入 NO_PROXY。先確認容器能解析名稱,再確認容器內程序是否真的讀取代理變數,並避免把代理密鑰直接寫入會被提交到版本庫的 Compose 檔案。
重開機後 TUN 或 Docker 代理失效,應該檢查哪裡?
先看 Clash 核心是否在 Docker 啟動前完成,接著檢查 TUN 介面、預設路由、mixed port 監聽狀態與 systemd drop-in 是否仍存在。若服務啟動順序不穩定,可以在符合企業政策的前提下調整服務依賴,但不要用無限重試掩蓋真正的路由衝突。也要確認主機更新後,核心權限、虛擬網路元件或防火牆規則沒有被重設。
相較於只靠桌面系統代理的工具,Clash 在這個場景的優勢是能把連線紀錄、規則命中、DNS 行為與 TUN 路由放在同一個可觀察流程中;而只支援單一 HTTP Proxy 的方案,常在 Docker Engine、CDN 重新導向或容器網路分層後變得難以追蹤。當你需要同時保留企業內部 Registry 直連、讓 Docker Hub 依規則走代理,並在下載速度不穩時快速切換策略組,Clash 的分流與透明接管會比單純修改 Shell 環境變數更容易維護。如果你正在尋找適用於 Linux、Windows、macOS 與其他支援平台的用戶端,可先從官方下載頁取得對應版本,再依本文的單一路徑原則逐步測試。