這是一篇關於 Docker 容器配置外部代理的實戰教程。

在內網開發、跨國業務或需要訪問受限資源(如 pip/npm/maven 源、GitHub)時,配置容器走代理是後端開發的必修課。很多開發者容易混淆 “Docker Pull 走代理”“容器內部程序走代理”,這兩者是完全隔離的配置體系。

本文將分層級為您解析,從守護進程到容器運行時,徹底打通網絡任督二脈。


Docker 容器網絡代理全攻略:從宿主機到外部服務器

📚 前置摘要 (TL;DR)

  • 分清對象:docker pull 加速需配置 Daemon(守護進程);給容器內的 curl/apt 加速需配置環境變量。
  • 關鍵地址: 如果代理在宿主機上,容器內不能填 127.0.0.1,請使用 host.docker.internal (Mac/Win) 或 172.17.0.1 (Linux)。
  • 關鍵設置: 務必確保你的daili軟件(Clash/V2rxx/Squid)開啓了 “允許局域網連接 (Allow LAN)”,否則容器連不上。

1\. 網絡拓撲與準備工作

在配置之前,必須明確代理服務器在哪裏:

  1. 場景 A - 代理在局域網另一台機器: IP 為 192.168.1.100,端口 7890
  • 直接使用該 IP 即可。
  1. 場景 B - 代理在宿主機(本機):
  • 容器內的 localhost 指向的是容器自己,不是宿主機。
  • Docker Desktop (Mac/Win): 使用 DNS 別名 host.docker.internal
  • Linux: 使用默認網關 IP 172.17.0.1 (需驗證網絡模式)。

2\. 第一層:配置 Docker Daemon (解決 docker pull 慢)

這層配置隻影響 拉取鏡像 的速度,不會 影響容器內部運行的程序。

Linux (Systemd)

創建或修改 systemd 配置目錄:

sudo mkdir -p /etc/systemd/system/docker.service.d
sudo vim /etc/systemd/system/docker.service.d/http-proxy.conf

寫入如下內容(替換為你的代理地址):

[Service]
Environment="HTTP_PROXY=http://192.168.1.100:7890"
Environment="HTTPS_PROXY=http://192.168.1.100:7890"
# NO_PROXY 列表中的地址不走代理,通常要把私有倉庫放進去
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.somecorporation.com"

應用並重啓:

sudo systemctl daemon-reload
sudo systemctl restart docker
macOS / Windows (Docker Desktop)
  1. 點擊 Docker 圖標 -\> Settings -\> Resources -\> Proxies。
  2. 開啓 Manual proxy configuration,填入 http://host.docker.internal:7890
  3. 點擊 Apply & Restart。

3\. 第二層:全局容器配置 (所有容器自動生效)

如果你希望本機啓動的所有容器默認都自動注入代理配置,可以修改用户級配置。

編輯 ~/.docker/config.json

{
 "proxies": {
   "default": {
     "httpProxy": "http://192.168.1.100:7890",
     "httpsProxy": "http://192.168.1.100:7890",
     "noProxy": "localhost,127.0.0.1,*.internal.domain"
   }
 }
}

效果: 之後執行 docker run 啓動的任何容器,都會自動帶有 HTTP_PROXY 等環境變量,無需手動指定。


4\. 第三層:單容器臨時配置 (最靈活,推薦)

在生產環境或調試時,我們通常只想讓特定的容器走代理。可以通過環境變量 -e 傳入。

命令行啓動 (Docker Run)

假設代理在宿主機 (macOS) 上:

docker run -it --rm \
  -e http_proxy=http://host.docker.internal:7890 \
  -e https_proxy=http://host.docker.internal:7890 \
  -e all_proxy=socks5://host.docker.internal:7890 \
  curlimages/curl \
  curl -I https://www.google.com

注意: 環境變量建議同時設置全小寫 (http_proxy) 和全大寫 (HTTP_PROXY),因為不同的軟件(如 apt vs pip vs go)對大小寫敏感度不同。

Docker Compose (推薦)

docker-compose.yml 中配置:

version: '3.8'
services:
  app:
    image: python:3.9
    environment:
      - HTTP_PROXY=http://host.docker.internal:7890
      - HTTPS_PROXY=http://host.docker.internal:7890
    command: pip install -r requirements.txt

5\. 第四層:構建時代理 (Docker Build)

這是最容易踩坑的地方。docker build 過程是隔離的,它不會繼承宿主機的網絡配置,也不會讀取 ~/.docker/config.json

如果你的 Dockerfile 裏有 RUN apt-get updateRUN pip install,必須通過 build-arg 傳入代理。

Dockerfile:

FROM ubuntu:22.04

# 定義參數,但不賦予默認值,避免硬編碼 IP 導致由於環境不同而構建失敗
ARG HTTP_PROXY
ARG HTTPS_PROXY

# 將參數轉為環境變量,以便後續 RUN 指令能讀到
ENV http_proxy=$HTTP_PROXY
ENV https_proxy=$HTTPS_PROXY

RUN apt-get update && apt-get install -y curl

構建命令:

docker build \
  --build-arg HTTP_PROXY=http://host.docker.internal:7890 \
  --build-arg HTTPS_PROXY=http://host.docker.internal:7890 \
  -t my-image .

6\. 驗證與排查

進入容器內部進行測試是驗證配置是否生效的唯一標準。

  1. 檢查環境變量:
docker exec -it <container_id> env | grep -i proxy
  1. 測試連通性:
# 測試能否通過代理訪問外網
docker exec -it <container_id> curl -v https://www.google.com
  1. 常見報錯:
  • Connection refused: 代理軟件沒開,或者沒開“允許局域網連接”,或者 IP 填錯了。
  • Could not resolve host: DNS 問題,嘗試配置 Docker 的 DNS 為 8.8.8.8

結語

Docker 的代理配置本質上就是環境變量注入

  • Daemon 配置是為了讓 Docker 引擎下載鏡像快。
  • Build-arg 是為了讓 apt/pip/npm 在構建時能聯網。
  • Run -e 是為了讓容器內的業務邏輯能訪問外部 API。

明確你的需求屬於哪個階段,就能精準配置。

下一步建議: 如果您正在使用 Docker Compose 編排微服務,並希望實現多個容器共享同一個網絡代理配置(而不是在每個 service 下面重複寫 environment),我可以為您展示如何利用 .env 文件或 YAML 錨點 來優雅地管理這些配置。需要看看嗎?