開發與 AI · Clash 技術部落格

Git、npm、Docker 不走 Clash?終端代理設定與超時修復

Git、npm 和 Docker 的代理來源不同,終端變數不會自動修復 docker pull。驗證本機連接埠後,按實際工具核對環境變數、設定檔或背景代理;下載成功後清理測試設定,並檢查退出後的直連。

  • Git
  • npm
  • Docker
  • WSL2
本文目錄

把代理位址寫進終端機後,下載仍然失敗,往往需要查工具實際讀取哪份設定。暫時變數、使用者設定與背景程序的設定不會自動同步。一次只處理原本出錯的工具,確認目前的代理連接埠可用後,再儲存需要的設定,避免換連接埠時留下衝突。

Git、npm 與 Docker 的請求由誰發出?

瀏覽器能存取 GitHub,不能證明命令列工具已使用相同代理。Git 會讀取自己的設定與環境變數,npm 還會讀取 npmrc,Docker Desktop 與 Docker Engine 則有獨立背景程序。三條命令同時失敗,也可能分別需要檢查各自的代理設定。

分別執行一個能復現問題的命令:git ls-remote https://github.com/git/git.git HEAD、npm ping、docker pull hello-world,並記下錯誤文字。

工具實際由誰發起請求

工具常見代理來源檢查入口
Git HTTPSGit 設定或 HTTP(S)_PROXYgit config 與 GIT_CURL_VERBOSE
npm環境變數、npmrc、registry 設定npm config get 與 npm ping
Docker DesktopDesktop 的 Proxies 設定Desktop 日誌與 pull 錯誤
Linux Docker Enginedockerd 的 daemon.json 或 systemd 環境journalctl -u docker

本機代理連接埠是否正在監聽?

在 Clash 用戶端查看 mixed-port 或 HTTP 連接埠,不能憑習慣假定一定是 7890。Windows 可用 netstat -ano,macOS 或 Linux 可用 lsof、ss 檢查連接埠;連接埠不存在時,任何工具設定都只會得到 connection refused。

用 curl 明確指定代理存取已知 HTTPS 地址,可以直接檢查本機代理能否使用。成功後,再把同一連接埠填入 Git 或 npm。若 curl 也失敗,檢查用戶端、節點或本機防火牆,不要繼續修改三個工具的永久設定。

臨時驗證本機 HTTP 代理
# 将 7890 换成客户端显示的 HTTP 或 mixed 端口
curl -I -x http://127.0.0.1:7890 https://github.com

# Linux 查看监听
ss -lntp | grep 7890

# Windows 查看监听
netstat -ano | findstr :7890

Could not resolve host 指向解析,Connection refused 常見於本機連接埠沒有監聽,TLS 或憑證錯誤不能靠增加超時時間解決。

僅對目前終端設定代理變數

HTTP_PROXY 和 HTTPS_PROXY 只對從目前終端啟動、且願意讀取它們的程式生效。先在一個新終端臨時設定,完成 git 或 npm 測試,關閉終端後自然失效。結果有效再決定是否寫進 PowerShell Profile、.zshrc 或 CI 環境。

NO_PROXY 應保留 localhost、127.0.0.1 和需要直連的內部網路網域。把所有內部網路請求也送進 Clash,會讓本機開發服務、公司儲存庫或 Docker 容器互訪產生新的問題。

一次終端會話的環境變數
export HTTP_PROXY=http://127.0.0.1:7890
export HTTPS_PROXY=http://127.0.0.1:7890
export NO_PROXY=localhost,127.0.0.1,.local

# PowerShell
$env:HTTP_PROXY="http://127.0.0.1:7890"
$env:HTTPS_PROXY="http://127.0.0.1:7890"

尋找 Git 代理的設定來源

git config --show-origin --get-regexp 可以顯示代理來自哪個檔案。命令沒有輸出時,通常只是 Git 沒有單獨儲存代理,並不是又發生了錯誤。舊用戶端留下的 http.proxy 指向已經關閉的連接埠時,即使環境變數正確,Git 仍可能繼續使用舊值。

需要固定 Git HTTPS 代理時,只寫入使用者級 http.proxy;不需要時用 --unset-all 清理。SSH remote 不走 Git 的 HTTP 代理,[email protected] 超時要另外檢查 SSH、ProxyCommand,或先改用 HTTPS 做對照。

查看、設定和清理 Git 代理
git config --show-origin --get-regexp '(^http\..*proxy$|^remote\..*\.proxy$)'

# 需要固定代理时再写入
git config --global http.proxy http://127.0.0.1:7890
git ls-remote https://github.com/git/git.git HEAD

# 以后改回环境变量或直连时删除
git config --global --unset-all http.proxy

npm 超時還要區分代理與 registry

npm 官方設定會讀取 HTTP_PROXY、HTTPS_PROXY,也可能在使用者或專案 .npmrc 中儲存 proxy、https-proxy 和 registry。registry 指向已停用的鏡像站時,換代理節點不會改變請求位址。

執行 npm config get proxy、npm config get https-proxy 和 npm config get registry,再用 npm ping 驗證目前 registry。專案目錄中的 .npmrc 可以覆蓋使用者設定,因此同一台電腦不同專案可能表現不同。

臨時環境變數已經生效時,不必再寫 npm 固定代理。確認 npm 沒有讀到環境變數後,再設定下面兩項。

核對、設定和清理 npm 代理
npm config get proxy
npm config get https-proxy
npm config get registry
npm ping

# 仅在确实需要 npm 固定代理时设置
npm config set proxy http://127.0.0.1:7890
npm config set https-proxy http://127.0.0.1:7890
npm ping

# 改回环境变量或直连时清理
npm config delete proxy
npm config delete https-proxy

docker pull 由背景引擎發起,改目前 shell 未必有用

Docker Desktop 有自己的代理設定。Windows 或 macOS 進入 Docker Desktop 的 Settings → Resources → Proxies,選擇 System proxy。

若系統代理沒有被識別,再選 Manual configuration 並填寫 Clash 的 HTTP 或 mixed 連接埠。

Docker 官方說明 Desktop 不讀取 daemon.json 中的 daemon proxy 設定,因此不要同時在兩個位置反覆修改。

原生 Linux Docker Engine 由 dockerd 拉取映像檔。查看 /etc/docker/daemon.json 是否已經存在,把下面的 proxies 欄位合併進原 JSON,不能整檔案覆蓋。儲存後驗證 JSON 與 daemon 設定,再重啟 Docker。

給容器內應用設定代理是另一項設定,它不會反過來修復 daemon 執行的 docker pull。

Linux Docker Engine 的 daemon 代理
# 把 proxies 合并进现有 /etc/docker/daemon.json,不要覆盖其他字段
{
  "proxies": {
    "http-proxy": "http://127.0.0.1:7890",
    "https-proxy": "http://127.0.0.1:7890",
    "no-proxy": "localhost,127.0.0.1,.local"
  }
}

sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker
docker info | grep -i proxy
docker pull hello-world
Docker Desktop
在 Settings → Resources → Proxies 檢查 Docker Desktop proxy 與 Containers proxy,應用設定後用 hello-world 做一次乾淨拉取。
執行中的容器
容器需要存取外部網路時再傳入代理變數,並為主機與內部網路位址設定 NO_PROXY。

進入 WSL 或容器以後,127.0.0.1 已經換了主人

Windows 上的 Clash 監聽 127.0.0.1,但 WSL2 或容器中的 127.0.0.1 指向它們自己。NAT 網路下要使用主機可達位址,並確認用戶端允許區域網路連線、Windows 防火牆只向需要的虛擬網段放行。鏡像網路模式的行為不同,應按目前 WSL 網路設定驗證。

先在 WSL 或容器裡 curl 主機代理連接埠;連連接埠都不通時,繼續改 Git 或 npm 沒有意義。連接埠可達以後,再決定用環境變數還是讓 Clash TUN 接管這類處理程序。

清理多餘代理設定,避免工具繼續連線舊連接埠

環境變數、Git 全域設定、npmrc 和 Docker 設定同時存在,換連接埠或結束用戶端時就不容易判斷哪個設定仍在生效。保留日常實際採用的設定方式,刪除測試期間寫入的多餘固定代理,並記錄哪些命令依賴它。

開啟新終端機,只重做這次修改的工具:Git 用 git ls-remote https://github.com/git/git.git HEAD;npm 用 npm ping;Docker 用 docker pull hello-world。

原本失敗的命令應得到結果,Clash 連線頁應出現對應請求;沒有使用的工具,不必為了驗收另外設定。

退出 Clash 後,工具不應繼續指向已經關閉的本機連接埠。若還出現 Connection refused,就繼續清理殘留的固定代理。

參考資料