為什麼 OpenHands 比「只裝一個 CLI」更容易整條鏈路逾時
許多人把 OpenHands 想成「再裝一個開源 Agent CLI」;實際上官方推薦的 Docker Compose 路徑會同時啟動後端、前端、沙箱執行環境與可能的 sidecar 服務。每一層都可能獨立對外:Docker Engine 向 registry-1.docker.io 拉 layer;容器啟動後內部的 Node 或 Python 又會去抓 npm registry 或 PyPI 鏡像;當 Agent 接到「修復某 GitHub issue」這類任務,還會觸發 git 協定與 api.github.com 的 REST 呼叫。任一環節在錯誤規則下被送去 DIRECT,表面症狀都是「OpenHands 起不來」或「Agent 卡住」,根因卻可能在 Docker、npm 或模型 API 的完全不同主機上。
第二個錯覺是「宿主機開了系統代理,容器就會跟著走」。在 Linux 上,docker pull 由 daemon 發起,預設不讀你在 shell 裡 export 的 HTTPS_PROXY;在 macOS/Windows 的 Docker Desktop 上,虛擬機內的 daemon 與宿主 Clash 的 mixed 埠又隔了一層 NAT。若只靠「瀏覽器能上 Docker Hub 網頁」來推論 pull 會成功,很容易在 docker compose up 第一屏就卡死。OpenHands 作為需要沙箱隔離的 Agent,容器網路堆疊比純終端 CLI 更複雜;方法論仍是:連線紀錄先行,分別觀測宿主 daemon 與容器內行程的 SNI,再談加規則。
第三層來自多提供商模型 API:你在設定檔裡選 Anthropic 就走 api.anthropic.com;換 OpenAI 或 Google Gemini 又會拉出完全不同的域名集合;若還透過 OpenRouter 等聚合閘道,SNI 可能又是第三套。OpenHands 的對話與工具呼叫會維持更久的 HTTPS/串流連線;任何一段在弱出口環境被誤判成直連,都會被解讀成「模型不回應」。因此本文刻意與站內 Cline SDK、Copilot CLI 文分流:那些文側重 IDE 擴充與 npm;OpenHands 則必須把 Docker Hub、GitHub 全鏈路 與容器內 npm 放在同一張排查表上。
1先復現:用連線紀錄對齊 Docker、GitHub 與模型 API 的真實主機
用你現場卡住的方式原封不動重跑:可能是 docker compose pull、從原始碼目錄 make build、或啟動後在 Web UI 提交第一個 Agent 任務。並行打開 Clash/Mihomo 前端的連線清單,把逾時前後出現的名字抄下來。Docker 路徑常見 registry-1.docker.io、auth.docker.io、production.cloudflare.docker.com;若 compose 指向 ghcr.io,請另記 pkg-containers.githubusercontent.com 等別名。GitHub 互動常見 github.com、api.github.com、objects.githubusercontent.com、codeload.github.com。npm 則是 registry.npmjs.org 與 tarball CDN。模型 API 依提供商記 api.anthropic.com、api.openai.com、generativelanguage.googleapis.com 等。
請區分宿主與容器兩個觀測面:daemon pull 時,紀錄可能在宿主 TUN 介面出現;容器內 npm ci 則可能走 bridge 網路,若未配置 daemon 代理或 TUN 未覆蓋轉發流量,會出現「宿主 curl 正常、容器 build 失敗」的分裂症狀。對 WSL2 上的 Docker Desktop,請把 Windows 宿主 Clash、WSL 與 VM 內 daemon 視為三層,可先讀 WSL2、Git、npm 與 Windows Clash,再把紀錄方法映射到 OpenHands 場景。
實務建議:同一次復現請固定「只看一種出口策略」——先選宿主 TUN,或先選 daemon.json 代理,避免疊加兩套路由卻以為規則沒生效。Docker pull 與容器內 npm 請在同一時間窗觀測,才能對齊 OpenHands 的多層出站。
2TUN、daemon 代理與環境變數:誰在幫 OpenHands 出外網
當連線紀錄顯示 Docker 或 git 相關主機仍標成 DIRECT,主軸只有兩條:宿主啟用 TUN 讓 daemon 與一般行程共用路由面,或在 Docker daemon 設定 HTTP/HTTPS 代理 指向 Clash 的 mixed/HTTP 入站埠。mihomo 埠號請與代理 URL 協定一致,並在 NO_PROXY 排除 localhost、內網段與私有 registry,避免把公司內部 Git 也硬送跨境節點。
Linux 上可在 /etc/docker/daemon.json 加入 proxies 區塊(具體鍵名依 Docker 版本文件為準),修改後需重啟 docker 服務。macOS/Windows Docker Desktop 則在 Settings → Resources → Proxies 填寫同一 mixed 埠。若你傾向全機 TUN 而不改 daemon,請確認 TUN 堆疊與 Docker 的 iptables/路由規則不衝突;長開前建議讀 Clash Verge Rev TUN 模式教學。對只想完成一次性安裝的使用者,可暫時開 TUN 跑完 docker compose pull && docker compose up 再關;但 Agent 長連線通常需要穩定出口,此時 TUN 加可觀測規則往往比每次手動 export 更省事。
本地非 Docker 開發路徑(直接 pip install 或 npm install)則回到終端代理:HTTPS_PROXY、ALL_PROXY 與 HTTP_PROXY 需與 mixed 埠對齊。OpenHands 後端若用 Poetry 或 uv,子行程也可能不吃變數;此時 TUN 的補漏價值更高。
3Docker Hub、ghcr.io 與鏡像拉取規則粒度
OpenHands 官方 compose 常引用 docker.io 或 ghcr.io 上的映像檔;兩者的 CDN 與 auth 端點不是同一組 SNI。規則只放寬 github.com 而漏掉 production.cloudflare.docker.com,就會出現「git clone 正常、compose pull 永遠轉圈」的分裂症狀。請以連線紀錄為準,把 auth、registry 與 layer CDN 各自對應到預期策略組,並檢查是否有更前面的 GEOIP 規則把流量早送到 DIRECT。
若你使用國內 Docker 鏡像加速器,請確認加速器域名本身也命中預期策略;否則可能出現「換了鏡像仍逾時」——根因其實是加速器 HTTP 端點被直連。企業環境若攔截 HTTPS,daemon 報錯常縮成泛用 TLS 失敗;這與純路由慢不同,盲目調大 DOCKER_CLIENT_TIMEOUT 只會在同個錯誤上等更久。站內 Mihomo Docker 部署 可作為「容器本身跑代理」的延伸閱讀;OpenHands 則是「Agent 依賴容器,容器要 pull 外網映像」的反向場景。
# Example only — replace PROXY; extend hostnames from your logs
rules:
- DOMAIN,auth.docker.io,PROXY
- DOMAIN-SUFFIX,docker.io,PROXY
- DOMAIN,production.cloudflare.docker.com,PROXY
- DOMAIN-SUFFIX,ghcr.io,PROXY
- DOMAIN-SUFFIX,githubusercontent.com,PROXY
- MATCH,DIRECT
4GitHub API、git clone 與 Agent 倉庫互動
OpenHands 的核心能力之一是對真實程式碼倉庫動手:clone、fetch、push(若你授權)都會觸發 GitHub 多個子域名。api.github.com 處理 REST/GraphQL;大檔與 release 資產常走 objects.githubusercontent.com;codeload.github.com 則服務 archive 下載。規則只放寬 github.com 首頁而漏掉 API 或物件儲存,會出現「Web UI 能貼 issue 連結、Agent clone 卻失敗」的假象。
若你使用 GitHub Enterprise Server 或 self-hosted Gitea,請以連線紀錄中的實際 Host 寫規則,不要套用公開 GitHub 模板。Personal Access Token 或 fine-grained token 的授權問題會表現成 HTTP 401/403,與路由逾時不同;網路對齊後若錯誤訊息轉為授權類敘述,應改走 GitHub 帳務排查。公開 GitHub 場景可對照站內 Cursor/GitHub/npm 分流,把 IDE 與 OpenHands 容器出口對齊到同一組 mihomo inbound。
5npm registry、前端建置與容器內依賴安裝
OpenHands 前端與部分工具鏈仍依賴 npm(或 pnpm/yarn,依 upstream 版本而定)。registry.npmjs.org 的 packument 與 tarball 可能走不同 CDN 別名;錯誤的 .npmrc 鏡像策略會把流量導向過期中介。容器內 build 若未繼承 daemon 代理且宿主未開 TUN,npm ci 會在 Dockerfile 的 RUN 步驟卡住,表現成「映像 build 失敗」而非執行期 Agent 問題。
企業 HTTPS inspection 若未把中介 CA 匯入 Node 信任鍊,錯誤常縮成泛用 TLS 失敗;請依資安流程處理,不要用 strict-ssl=false 當第一解法。若公司環境必須走指定 proxy 埠,也要避免 .npmrc 的 proxy 指向已下線本地轉發,而 Clash 實際監聽的是另一埠——這類設定打架在紀錄中會呈現短暫連得上與長時間無回應交錯。
6Claude、GPT、Gemini 與多提供商模型 API 分流
OpenHands 支援多家 LLM 後端;對 Clash 而言,規則集必須跟著你的提供商設定走,而不是寫死單一 AI 域名。Anthropic 路徑常見 api.anthropic.com;OpenAI 涉及 api.openai.com 及可能的 CDN 別名;Google Gemini 相關呼叫可能落在 generativelanguage.googleapis.com 等 Google API 主機。若規則習慣性把整段 googleapis.com 直連,在弱出口地區可能讓 Gemini 提供商間歇不可用,而 Claude 卻正常——這會被誤解成「OpenHands bug」,實則是策略組不一致。
Agent 長對話與串流回應會維持更久的 HTTPS 連線;請在 Web UI 實際提交任務、觀察推理階段連線是否從 PROXY 抖回 DIRECT。HTTP/3/QUIC 相關行為會讓某些邊界設備更敏感;根因仍應回到具體失敗主機與規則命中。站內 Claude/Anthropic 分流、ChatGPT/OpenAI 分流 與 Gemini 與 TUN 可作為各提供商細節的延伸閱讀;本文聚焦 OpenHands 在 Docker 與 GitHub 並行時的出口一致性。
7DNS、Fake‑IP 與規則解析一致性
TUN 並不能替代 DNS 調校:若同一條 docker compose up 早上失敗、下午又自行恢復,優先懷疑 fallback DNS 競態、fake-ip-filter 漏項目,或路由器與桌面端雙層劫持。建議對照 Meta/Mihomo DNS 防洩漏指南,將 Docker Hub、GitHub、npm 與模型 API 主機一起放入要監測一致性的清單,而不是只盯瀏覽器常用網站。
當 fake-ip 與內網/本機 registry 互動時,若規則與解析視圖不一致,容易出現連線紀錄看似命中、應用卻報連不到的假性故障。此時請用小範圍的 curl -v 在宿主與容器內各測一次,確認 nameserver-policy 是否對特定後綴指定了不合適的 upstream。對開發者而言,最浪費時間的路線是不停更換節點、卻從未讓 DNS 與規則在同一視圖下被檢視。
提醒:公司 HTTPS inspection 會改寫終端與容器對 CA 的信任鍊;請先依資訊安全流程處理,不要用關閉校驗取代治理。Docker 與 npm 在容器內可能需要額外匯入企業根憑證。
與站內其他「Agent × Clash」文章怎麼分工
若你同時評估 Cline SDK 與 OpenHands,Cline 文見 Cline SDK/CLI 與 TUN,側重 IDE 擴充市集與 MCP;OpenHands 則以 Docker 沙箱與 GitHub 倉庫互動為主。GitHub Copilot CLI 的 npm 排查在 Copilot CLI 與 npm;OpenAI Codex CLI 見 Codex CLI 與 TUN/DNS。每篇刻意不重複 write-up 細節,但方法論共享:紀錄先行、規則粒度跟著證據走、宿主與容器分層觀測(OpenHands 特有)。
8驗收清單:把「感覺好了」變成可回放的操作手冊
- 以單一出口策略(TUN 或 daemon 代理)復現後,確認 Docker Hub/ghcr.io、GitHub 與你使用的模型 API 主機在紀錄中長時間維持預期策略組,而非在 DIRECT 與代理間來回抖動。
- 重跑
docker compose pull與docker compose up:對照是否仍能穩定完成映像拉取與容器啟動,排除被本地 cache 遮蔽的假成功。 - 在 Web UI 提交實際 Agent 任務:包含 git clone 與至少一輪對 Claude、GPT 或 Gemini 的長對話,留意串流連線是否仍出現非預期直連。
- 若使用原始碼路徑,分別在宿主與容器內重跑
npm ci或等價安裝指令,確認兩邊命中一致。 - 若網路路徑已對齊但錯誤訊息轉為 API 金鑰、配額、Docker 認證或 GitHub 授權類敘述,請改走官方帳務排查,避免把商業限制誤修成路由問題。
常見問題(以連線紀錄閱讀)
宿主 curl registry-1.docker.io 正常,為何 docker pull 仍失敗? curl 走你的 shell 代理堆疊,pull 走 daemon;需 daemon 代理或 TUN 覆蓋 daemon 出站。只開 TUN、不改 daemon 夠嗎? 多數 Linux 場景夠,但請用紀錄驗證;少數 Docker 網路模式需額外調整。Agent 能推理但 push 失敗? 可能是 token 權限,也可能是 api.github.com 規則漏網;看紀錄再判斷。TUN 會不會影響公司 VPN? 會,需理解路由優先序與 split tunnel 政策。
開源、授權與本站下載
OpenHands 與前身 OpenDevin 以 upstream 官方倉庫與授權條款為準;mihomo 與各圖形前端亦請查各自授權。日常安裝與更新建議優先使用本站 下載區 與 設定說明總覽,先釐清系統代理、mixed 與 TUN 的差異,再落盤到長期備份設定;本文不重製 OpenHands 的 release note。
結語
2026 年 5 月的 OpenHands 把自主編程 Agent 的想像拉到可部署的 Docker 堆疊上,也把「映像拉取」「GitHub 互動」「npm 建置」與「多提供商模型 API」壓在同一條工程故事線裡:任何一段落在錯誤的對外視圖,都會被放大成整體不可用。把 Clash/Mihomo 連線紀錄當唯一真相來源,分層觀測宿主 daemon 與容器內行程,先對齊 Docker Hub、GitHub 與模型 API 的 hostname 粒度,再談 TUN 與 DNS,可以顯著降低無效換節點與盲調逾時的時間成本。
與只提供一鍵翻牆概念、但欠缺主機級觀測面的工具相比,Clash 生態把策略命中細節留在工程師可閱讀的介面上:你能看到 registry-1.docker.io 是否真的走了代理,也能看到 api.anthropic.com 長連線有沒有在 Agent 對話中途被規則送去直連。對需要在本機或內網長期跑 OpenHands、又要跟進 upstream 快速迭代的團隊來說,這種可回放性本身就是營運資產。
若你想把本文流程變成固定 runbook:建議先備份現有設定,再以小步驗證把 Docker、GitHub、npm 與模型 API 相關域名寫成可版本化的 rule-providers 片段,並記錄每次事故對應的連線截圖或文字紀錄,讓下次排查不必從零猜主機。你也可以免費下載 Clash,用本文順序對照邊界環境快速收斂 OpenHands 的安裝與 Agent 連線問題範圍。