問題長什麼樣:Pulling、TLS handshake timeout,與你真正卡住的位置

容器開發最煩的情境之一,是docker pull一跑就卡在「Pulling fs layer」「Pulling」「Waiting」之類的狀態,半天沒有進度條;或直接噴Tls: handshake timeoutTLS handshake timeout這類字眼。對照搜尋意圖來看,許多人不是不知道要開代理,而是搞不清楚流量到底走的是哪條路:瀏覽器能上 Docker 官網,不代表Docker daemon 拉回映像的那一條 HTTPS 連線也順利接上同一套代理。

本文假設你已在使用 Clash 系客戶端(多半是搭載 Mihomo/Meta 規則核心),並且希望用TUN(虛擬網卡通路)讓對外出站盡量在「可查、可對照規則」的前提下走通。我們不保證任何節點或第三方鏡像庫/Registry 一定可用;重點是給出一套可追溯的排查順序,讓你下次遇到 Docker Hub/registry 級的 TLS 異常時,不再盲目試錯。

為什麼你 export 過 HTTP_PROXY,docker pull 還是能失敗?

常見的第一個落差在於:Docker daemon 不等於你在終端機裡的那一個 shell 行程。許多使用者習慣在.zshrc(或適用於你的工作階段的檔)寫HTTPS_PROXY=http://127.0.0.1:xxxx,對curlgit可能有效(尤其在子行程會繼承環境變數時);但對大多數發行版的 Docker 引擎而言,它自己的對外請求流程通常不會讀你隨便在 shell export 的那一組變數——除非你做更深層的組態調整。

第二個落差是「系統代理」與瀏覽器:許多使用者僅開啟客戶端的系統 Proxy,對 Chrome/Edge/Safari 有效,但對 Docker daemon 仍然未必成立。daemon 對 registry.docker.io/CloudFront/各種 CDN 節點建立的是程式層發起的並行 HTTPS,而且可能因鏡像層級分片而對多組主機重複發起連線。若其中任何一組主機在規則上被錯誤放行成直連或被旁路劫持,整體就會卡在「看得到 Pulling/沒有錯誤碼但很慢」的假死感裡。

第三個常見問題是時間與證書路徑:TLS handshake 若發生在網路上半段被封鎖或被劣質劫持,典型症狀會是EOFreset by peer,或你看到的就是TLS handshake timeout它未必代表鏡像壞檔或磁碟問題,更多時候代表的是「對外信道沒對上你以為的那一條 Clash/節點出口」。

開始修復前:三分鐘前檢清單

  • 確認節點本身穩定性:同一節點若連一般 HTTPS(例如對外curl -I https://registry-1.docker.io/v2/)就已抖動嚴重,拉映像自然也會卡在握手/下載任一階段。
  • 先關掉其他強改路由的工具:除 Clash TUN 外,若同日還在跑企業級 VPN/另一套「全系統加速」,兩個程式可能輪番改寫預設路由,造成「規則看見走代理/實際封包溜走」的假性成功。
  • 對照映像來源是否只有 Docker Hub:許多 Dockerfile 基底層來自docker.io/library/...,但也可能混進私有 harbor、GitHub Packages 等。不要只對 registry.docker.io 放寬規則卻忘掉下一跳網域
  • Docker Desktop 與原生 Linux-engine 區分清楚:桌面版的網路程式模型與本機 systemd 底下的 daemon 並不完全相同。

公司網路與 DPI:若企業對非標埠或異常長連線有更嚴格檢查,你看到的多半不是單點blocked字樣而是一連串逾時。TUN + 對應協定出站仍應對照資安規範後再使用,本文僅論技術面。

為什麼 Clash「TUN 模式」在這種場景常被證明有用?

傳統本機 SOCKS/HTTP Mixed Port(例如127.0.0.1:7890)仰賴應用程式主動認得代理;而 TUN 則是靠作業系統路由表/虛擬網界面,對多數對外程式較為「透明」,讓資料面封包在未明確設定HTTPS_PROXY的情況下,也有機會進入規則引擎視野。

docker pull這類大量使用底層 socket 的情境,這意味著你不用先猜「daemon 有沒有讀到環境變數」,而是用更底層的網卡與規則命中去回答問題。對排錯者來說,只要 Clash 日誌能清楚看到對應目標正在被轉發到預期的策略群組/節點,你就已經把「到底是不是走代理」從玄學變成可對照的證據。

區網與本機別被誤送代理:啟動 TUN 後若印表機、NAS、區網測試全掛掉,請檢視規則前段對192.168.0.0/1610.0.0.0/8172.16.0.0/12等私網區段是否有明確DIRECT規則;不要在未理解MATCH順序前就整包送走。

分步操作:把 Docker Hub 拉回映像對齊 Clash TUN

下面是實務上適用於多數桌面環境的順序,你可依平台差異細調,但請維持「先證路由、後證協定」的邏輯。

  1. 準備並啟用 TUN(含 OS 授權):在 Clash/Verge 類客戶端打開 TUN,macOS 可能要求延伸功能/密碼,Windows 會出現網卡與防火牆提示。未授權成功前不要急著測 pull,否則 log 只看到偶發復原。
  2. 確認 routing 自動接管已開:典型 Mihomo YAML 區塊(範例骨架,請以你自己的核心/GUI 對照)會包含自動偵測對外網路等設計;若在 Linux 上使用需額外套件/權限,請優先選擇對應教學與發行套件。
  3. 用 curl 對 registry 做小步驟驗證:在宿主機對registry-1.docker.io等端點執行簡短的 HTTPS HEAD/GET(注意頻率,避免對公共服務打壓);若宿主已穩且 pull 仍掛點,把焦點轉移到 Docker Desktop 或小虛機裡的流量是否被二度隔離。
  4. 拉 Clash connections/日誌看「命中的 host」:啟動 pull 的同時對照視窗,應看得到多個對外HTTPS連線並匹配你的境外策略;若發現DOCKER-REGISTRY這類對象直連到公司封鎖路徑,回到規則 provider 順序調整。
  5. Docker Desktop 代理欄位的角色:若你已填 HTTP/HTTPS Proxy 指向127.0.0.1對應埠,與「僅開 TUN、不開欄位」可互相比對:哪一側更穩就保留該側作為標準操作流程;部分使用者會發現TUN-only即可,有些則適合並存以避免引擎內部旁路。
  6. 最後復測小映像並還原除錯等級:請用標籤明確的官方小映像測試,成功後把log-leveldebug拉回info類等級。
# Example YAML skeleton (adapt to your profile and core version)

tun:
  enable: true
  stack: system
  auto-route: true
  auto-detect-interface: true
  # Confirm dns-hijack / mtu with official docs before enabling blindly

daemon.json、persisted proxies 算不算「標準解法」?

在 Linux/某些企業發行環境裡,你會看到有文件建議/etc/docker/daemon.jsonproxies並由 systemd 環境包住引擎。對離線環境或政策要求所有程式只能走核准出口站的使用者來說,這條線合理且可稽核。但在日常桌面開發中,許多人只是單機要對 Docker Hub「快一點、穩一點」,若先複雜修改 daemon.json 而沒有先用 TUN+規則找到「對象 host 對不對」,常常會卡在「daemon 對某個 CDN 類位址仍以為要直連」的困境裡。建議將 daemon proxies 視為備援項,而不是第一個旋鈕

為什麼還看得到 TLS timeout:MTU/DNS/fake-ip/多層 NAT

若你已確認對外策略與 Connections 對得上,仍偶發TLS handshake timeout,下一層級常見問題是:

  • 過小的 MTU 與分拆封包異常:複雜內網或隧道疊隧道時會出現難抓的問題;對照宿主與 daemon 宿主(例如 Linux VM)兩側 MTU/介面統計可作輔證。
  • DNS 在多處設定互相打架:路由器、VPN、Docker Desktop 內建 DNS forwarding、Ubuntu 上的resolved,任意兩種同時發威就可能讓你看到「對外 IP ping 類測試還過,HTTPS 協定細節異常」。啟動 TUN+對應的 DNS hijack 時,請先理解 GUI 對系統 Resolver 會做什麼。
  • fake-ip/redir-host 類模式與舊工具的預設:若你只跟著網路上的模糊抄寫而把 DNS 區塊關過頭,可能換來「瀏覽器看起來沒問題、特定背景行程失敗」。這時應回看官方文件對 enhanced-mode/dns 對照表的說法。

分層對照問題:遇到怪異逾時時,將「宿主 shell」「Docker Desktop」「容器內部」三種視角拆開看;許多問題其實是第二層虛擬機或 WSL/Hyper-V 網路沒接住你以為的那一條 TUN。

驗證方式:如何把「真的修好了」寫成一個可被覆核的紀錄

  • 同一映像標籤可重複拉兩次以上:第一次冷啟會慢,但若第二次仍需跑完整握手並長時間卡住,就代表仍有對象出站沒穩。
  • Clash 日誌在 pull 區間對應有連線紀錄:若規則寫對,但紀錄中完全沒有 registry 對象連線片段,請懷疑是否流量走旁路或未受該守護程序管控。
  • 對照不同 registry:若換成自家私有倉立刻成功,問題多半仍集中在對 Docker Hub CDN 的出口路徑,而不是本機鏡像層問題。

與本篇相關的常見問題

Pulling fs layer 顯示了但數字不快跑,算不算壞掉了?

不一定是壞軟體:大型分層在多個節點排隊、或 CDN 端調度很慢時,介面仍可長時間顯示同一列。對照標準是它相對過去在同一網路環境是否仍正常,以及對端 RTT 是否合理;並請用本篇 TUN/Connections 對照流程排除「走錯路線」問題。

換成國內或其他鏡像站是不是更好?

鏡像註冊表可以解決區域 QoS/政策問題,但也帶來延遲更新與非官方同步風險。若你是在受控環境被要求使用公司鏡像,請以資安規範為準。Clash/TUN 仍是「對外信道」層級的工具,並不替你承擔供應鏈驗簽義務。

伺服器上要跑 daemon,又沒桌面 GUI,怎麼套用思路?

核心是同一套問題「daemon 對外信道」:TUN/透明代理類方案在伺服器上可以透過對應的 gateway 組態達成類似效果,但牽涉iptables/nft/systemd-networkd 等政策,請依發行套件與 SRE/維運準則實施。本文側重桌面開發者路徑,僅提醒你別把 shell 環境代理當成唯一答案

那為什麼仍推薦用持續維護的 Clash/Mihomo 系客戶端?

市面上不少「加速器」強調一鍵通,但往往缺少可審視的規則命中與明確的對象 host 對照介面;對容器開發者來說,你需要的是:能知道 registry CDN 對象是否走對策略、能否分開直連國內與國外出站、並在核心更新後仍支援新式協定。一些舊世代工具在停更後就無法與新式 TLS/HTTP2/QUIC/企業環境對齊,遇到的就只剩「看得到逾時/看不到原因」。相較之下,沿用Mihomo/Meta系規則模型與視覺化 Connections 面板,對照 Docker pull 的流量型態時,往往能直接省下來回重灌系統級設定的時間;若你已經在桌面端用過 TUN 處理 git/npm/curl,同一套對容器 daemon 對外信道也更容易延續,而不是在每個 toolchain 換一套玄學摸索。

若你希望把「映像拉回、套件下載與日常工作瀏覽」收斂進統一、可對照規則與出站策略的流程,並在必要時再打開細緻分流與提供者更新,可先從官方管道取得對應平台客戶端:

免費下載 Clash 客戶端