本文目錄
開發環境最容易設錯的地方,是把電腦上可用的代理位址直接複製到所有終端機與容器。真正需要確認的是:哪個程序發出錯誤,它能否連到代理所在的主機。連線測試通過後再儲存長期設定,也要讓資料庫等內部服務保持直連。
docker pull、WSL 下載與容器請求的代理設定
發生錯誤由哪個程式發起?
| 失敗動作 | 發起請求的程式 |
|---|---|
| curl / apt / git 在 WSL 裡超時 | WSL 發行版中的處理程序 |
| docker pull 超時 | Docker Desktop 或 Docker Engine 守護處理程序 |
| RUN apt-get 在 build 時超時 | BuildKit / 建置容器 |
| 啟動後的應用請求失敗 | 執行中的容器 |
Windows 上的 Clash 監聽 127.0.0.1,只保證 Windows 本機能存取。WSL2 預設執行在 NAT 虛擬網路裡,容器也有獨立的網路環境;它們存取 127.0.0.1 時通常連線的是自己,不是宿主機。
- Windows 上的 Clash監聽區域網路可達的 mixed-port
- WSL2使用主機位址存取該連接埠
- Docker 建置顯式接收 HTTP_PROXY 和 HTTPS_PROXY
- 容器內工具再處理 Git、npm 或套件管理員
Windows、WSL2 和各個容器存取 127.0.0.1 時,通常連接的是各自的網路環境。代理位址應填寫目前環境能存取的宿主機位址。
讓 WSL 能存取 Windows 的代理連接埠
先在 Clash 查看實際的 HTTP 或 mixed-port,常見示例是 7890,但你的用戶端可能不同。WSL 使用主機 IP 存取時,這個連線會被當作區域網路連線,用戶端需要允許 LAN 存取,並監聽 WSL 能到達的位址。
允許 LAN 會擴大連接埠可達範圍。只在可信的家庭或單位私有網路使用,並讓 Windows 防火牆限制來源;不要把無認證代理暴露到公共 Wi-Fi 或公用網路。完成測試後若不再需要,可以關閉 LAN 存取。
預設 NAT 與鏡像網路的主機位址
預設 NAT 模式下,可以在 WSL 讀取預設路由的下一跳,它通常就是 Windows 主機在 WSL 虛擬網路中的位址。Windows 11 22H2 及後續版本啟用 mirrored networking 後,WSL 可以直接透過 127.0.0.1 存取 Windows 服務。
HOST_IP=$(ip route show | grep -i default | awk '{ print $3 }')
CLASH_PORT=7890
echo "Windows host: $HOST_IP"
curl -I -x "http://${HOST_IP}:${CLASH_PORT}" https://example.com這條 curl 得到 HTTP 回應後,才有必要設定 WSL 環境變數。若代理連接埠直接回傳 Connection refused,問題在 Clash 監聽、允許 LAN 或防火牆;若連接埠可達但外部請求 timeout,再檢查節點和規則。
設定 WSL shell 的 HTTP_PROXY 與 HTTPS_PROXY
HOST_IP=$(ip route show | grep -i default | awk '{ print $3 }')
CLASH_PORT=7890
export HTTP_PROXY="http://${HOST_IP}:${CLASH_PORT}"
export HTTPS_PROXY="http://${HOST_IP}:${CLASH_PORT}"
export NO_PROXY="localhost,127.0.0.1,::1"
curl -I https://example.com暫時變數供目前終端機啟動的程式讀取。用 git 或 curl 重做同一 HTTPS 請求,成功後再依 shell 類型寫入自己的啟動檔案;curl 存取 HTTP 位址時讀取小寫 http_proxy,不能只靠 HTTP_PROXY。
apt 的 HTTP 傳輸讀取小寫 http_proxy、no_proxy,或自己的 Acquire::http::Proxy 設定;用 sudo 啟動時還要確認環境是否保留。不要把上方變數段當成所有工具通用的代理設定。
Windows 支援的 WSL 版本也可以在 .wslconfig 使用 autoProxy=true,讓 WSL 匯入 Windows 的 HTTP 代理資訊。啟用後要重啟 WSL,並檢查實際變數值。
NO_PROXY 應包含只在 WSL 內部提供的服務,避免存取 localhost 時繞到 Windows 代理。公司內部網域和私有網段是否加入,要按實際網路決定。
Docker Desktop 與獨立 Engine 的代理入口
Docker Desktop 拉取鏡像與 WSL shell 下載由不同處理程序發起。只在 WSL 中 export HTTP_PROXY,不會自動設定 Desktop 的鏡像拉取。
開啟 Docker Desktop 的 Settings,在 Resources / Proxies(標籤可能隨版本變化)填寫主機可用的 HTTP、HTTPS 代理,並應用設定。
頁面分為 Docker Desktop proxy 和 Containers proxy 時,拉取映像檔要檢查 Containers proxy;只有 Containers proxy 未設定時,Docker Desktop proxy 才作為備援。修改後用 docker pull 驗證。
Docker 官方文件明確說明,Desktop 不讀取 daemon.json 中的守護處理程序代理設定。不要因為 WSL 終端已經能存取,就跳過 Docker Desktop 自己的代理設定。
若使用的是獨立 Linux Docker Engine,而不是 Docker Desktop,才按 Engine 文件在 daemon.json 或 systemd 環境中設定守護處理程序代理,並重啟 Docker 服務。先確認自己執行的形態,避免改了一個根本不被讀取的檔案。
為映像檔建置和執行容器分別傳入代理
Docker 的用戶端設定可以為新容器和建置自動注入代理環境,也可以在單次命令裡顯式傳入。建置時用 --build-arg,執行階段用 --env;不要在 Dockerfile 裡用 ENV 固化帶認證資訊的代理位址,映像檔歷史和設定可能把它留下。
下方範例在含有 Dockerfile 的專案目錄中執行,demo-app 是這次建置的映像檔名稱,可依自己的專案替換。這不是獨立連通測試;先用前文的 curl 檢查代理連接埠是否可達。
CLASH_PROXY=http://host.docker.internal:7890
docker build \
--build-arg HTTP_PROXY="$CLASH_PROXY" \
--build-arg HTTPS_PROXY="$CLASH_PROXY" \
-t demo-app .
docker run --rm \
--env HTTP_PROXY="$CLASH_PROXY" \
--env HTTPS_PROXY="$CLASH_PROXY" \
--env NO_PROXY="localhost,127.0.0.1" \
demo-appDocker Desktop 通常提供 host.docker.internal 指向主機。原生 Linux Engine 是否可用取決於環境,需要用明確的主機閘道或額外 host-gateway 設定。命令執行前,用容器內的 curl 或應用程式記錄驗證這個主機名稱和連接埠確實可達。
NO_PROXY:讓資料庫與內部服務保持直連
資料庫名稱、Compose 服務名稱、localhost 和內部網段通常不應交給外部代理。把實際內部網域加入 NO_PROXY,避免應用程式存取 db:5432、redis:6379 時先轉到 Windows 代理。不同工具對萬用字元和 CIDR 的支援不同,設定後要在目標程序中輸出變數的值,並發出實際請求。
代理位址若含使用者名稱或密碼,不要寫進公開的 compose.yaml、Dockerfile 或映像檔。使用本機環境檔案或專案的 secret 管理方式,並確保日誌不會把完整 URL 打出來。
按實際使用完成四次驗證
- WSL 中 curl 透過 Windows Clash 得到回應
- docker pull 可以拉取一個小映像檔
- docker build 的網路步驟不再超時
- 執行容器既能存取外部網路,也能直連內部服務
