開發與 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,並記下錯誤文字。

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

工具實際由誰發起請求

工具常見代理來源先看的結果
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

先確認 127.0.0.1 上確實有人接請求

在 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

終端先做一次臨時測試,不急著寫進啟動檔案

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 做一次乾淨拉取。
Linux Docker Engine
先用 dockerd --validate 驗證 daemon.json,再重啟服務;失敗時查看 journalctl -u docker。
執行中的容器
容器需要存取外部網路時再傳入代理變數,並為主機與內部網路位址設定 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 ls-remote https://github.com/git/git.git HEAD、npm ping 和 docker pull hello-world。三者都應成功,Clash 的連線頁也應出現對應請求。

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

參考資料