Docker 代理配置教程 – wiki基地


Docker 代理配置教程:穿越网络限制的完整指南

在企业环境、受限网络或任何需要通过代理服务器访问互联网的场景下使用 Docker 时,网络配置往往是第一道障碍。Docker 需要网络连接来拉取镜像、构建镜像中的软件包依赖、以及运行容器中的应用程序访问外部服务。如果你的网络需要通过代理服务器,那么正确配置 Docker 的代理设置至关重要。

本教程将详细阐述 Docker 代理配置的各个方面,包括为什么需要配置代理、Docker 代理的三种主要配置场景(守护进程、构建过程、容器运行时)以及如何在不同环境下进行配置。我们将深入探讨每种方法的细节、提供具体的配置步骤和示例,并包含故障排除技巧,帮助你全面掌握 Docker 代理配置。

为什么需要配置 Docker 代理?

在典型的网络环境中,你的计算机可能无法直接访问互联网。所有外部流量都需要通过一个或多个代理服务器进行中转。这些代理服务器可能用于:

  1. 安全性控制: 过滤恶意网站、监控网络流量。
  2. 缓存: 加速常用资源的访问(如软件包仓库)。
  3. 合规性: 强制执行组织的网络访问策略。
  4. 带宽管理: 控制和优化网络资源的使用。

Docker 在其日常操作中需要进行网络通信:

  • 拉取镜像: 从 Docker Hub、私有仓库或其他注册中心下载镜像文件。
  • 构建镜像: 执行 Dockerfile 中的指令,例如 RUN apt-get updateRUN yum installRUN curlRUN go getRUN npm install 等,这些指令可能需要从外部下载软件包或依赖。
  • 运行容器: 容器内部运行的应用程序可能需要访问外部服务,如数据库、API、第三方服务等。

如果你的网络要求通过代理访问外部,而 Docker 没有正确配置代理,那么以上操作都会失败,表现为拉取镜像超时、构建卡住或失败、容器内应用无法连接网络等问题。

Docker 代理配置的三个关键场景

理解 Docker 代理配置的关键在于认识到 Docker 在不同阶段和组件中对网络的需求是独立的。这意味着为一个场景配置了代理,不一定对其他场景生效。通常需要配置代理的三个主要场景是:

  1. Docker Daemon (守护进程) 代理:

    • 作用: 控制 Docker 守护进程本身的出站网络请求
    • 何时需要: 主要用于 Docker 守护进程需要直接访问网络的操作,最常见的就是拉取镜像 (docker pull)推送镜像 (docker push) 到注册中心。守护进程在与注册中心通信时,会使用此代理设置。
    • 如何配置: 通过修改 Docker 守护进程的配置文件 (daemon.json) 或操作系统级别的服务配置。
  2. Build Time (构建时) 代理:

    • 作用: 控制构建镜像过程中执行的命令的网络访问。
    • 何时需要: 当你在 Dockerfile 中使用 RUNADDCOPY 指令执行需要下载外部资源的命令时(例如安装软件包、下载文件、执行 npm installgo get 等)。这些命令在构建镜像的环境中执行,而不是在最终运行的容器中。
    • 如何配置: 通过 Dockerfile 中的 ARGENV 指令结合 docker build --build-arg 参数,或者在较新版本的 Docker 中通过守护进程配置自动传递构建参数。
  3. Runtime (运行时) 容器代理:

    • 作用: 控制容器内部运行的应用程序的网络访问。
    • 何时需要: 当你运行一个容器 (docker run),并且容器内运行的应用程序需要连接外部网络时(例如一个 Web 服务器需要调用外部 API,或者一个脚本需要 curl 下载文件)。
    • 如何配置: 通过在 docker run 命令中使用 -e 参数设置环境变量,或者在 docker-compose 文件中设置容器的环境变量。

理解这三个场景的区别至关重要。例如,配置了守护进程代理可以让你拉取镜像,但如果你的 Dockerfile 中有 RUN apt-get update,这个命令依然可能因为没有构建时代理而失败。同样,镜像构建成功后,容器运行时如果需要访问网络,还需要单独配置运行时代理。

接下来,我们将分别详细介绍这三种配置方法。

方法一:配置 Docker Daemon 代理

这是 Docker 守护进程本身的代理设置,影响到所有由守护进程发起的网络请求,最主要的是拉取和推送镜像。

配置原理:

Docker 守护进程会读取其配置文件 daemon.json 中的 httpProxyhttpsProxynoProxy 字段来设置代理。这些字段对应于 HTTP_PROXY、HTTPS_PROXY 和 NO_PROXY 环境变量,但它们是针对守护进程进程设置的,而不是用户 shell 环境。

配置步骤:

  1. 创建或编辑 daemon.json 文件:

    • Linux 系统:通常位于 /etc/docker/daemon.json
    • Windows Server (Docker EE/CE):通常位于 C:\ProgramData\docker\config\daemon.json
    • macOS / Windows (Docker Desktop):通过 Docker Desktop 的图形界面配置,或者直接编辑其内部使用的 daemon.json (不推荐直接手动编辑,优先使用 UI)。

    如果文件不存在,创建它。如果存在,确保它是有效的 JSON 格式。

  2. 添加或修改代理配置:
    daemon.json 文件中添加或修改以下字段:

    json
    {
    "httpProxy": "http://your_proxy_server:port",
    "httpsProxy": "http://your_proxy_server:port",
    "noProxy": "localhost,127.0.0.1,docker-registry.example.com,.corp"
    }

    • httpProxy: 设置用于 HTTP 请求的代理服务器地址(包括协议、主机名/IP 和端口)。
    • httpsProxy: 设置用于 HTTPS 请求的代理服务器地址。注意: 即使目标是 HTTPS,代理服务器本身通常还是通过 HTTP 协议访问(所以通常是 http://... 而不是 https://...),这取决于你的代理类型(例如,这是一个 HTTP/HTTPS 代理)。请根据实际代理服务器类型填写。如果 HTTP 和 HTTPS 使用同一个代理,可以填写相同的值。
    • noProxy: 一个逗号分隔的列表,列出不需要经过代理的主机名、IP 地址或域名后缀。例如,内部的 Docker 仓库地址、内网服务地址等。*.corp 这样的通配符通常是支持的(具体取决于 Docker 版本和实现)。

    带认证的代理:
    如果你的代理需要认证,你可以将用户名和密码包含在 URL 中(不推荐用于生产环境的敏感密码,应考虑更安全的认证方式,如 NTLM、Kerberos 或通过环境变量注入,但 daemon.json 本身不支持环境变量):

    json
    {
    "httpProxy": "http://username:password@your_proxy_server:port",
    "httpsProxy": "http://username:password@your_proxy_server:port",
    "noProxy": "localhost,127.0.0.1"
    }

    请注意对密码中的特殊字符进行 URL 编码。

  3. 重启 Docker 守护进程:
    配置更改后,必须重启 Docker 守护进程才能生效。

    • Linux (使用 systemd):
      bash
      sudo systemctl daemon-reload
      sudo systemctl restart docker
    • Linux (使用 Upstart 或 SysVinit):
      bash
      sudo service docker restart
      # 或
      sudo /etc/init.d/docker restart
    • Windows Server:
      powershell
      Restart-Service docker
    • macOS / Windows (Docker Desktop):
      通过 Docker Desktop 应用的菜单或设置中找到 “Restart Docker” 或 “Quit” 然后重新打开。
  4. 验证配置:
    重启后,可以通过 docker info 命令查看 Docker 守护进程的配置信息,其中应该包含你设置的代理信息:

    bash
    docker info | grep -i proxy

    你应该能看到类似 Http Proxy: http://your_proxy_server:port 的输出。

    接下来,尝试拉取一个公共镜像来测试代理是否生效:
    bash
    docker pull hello-world

    如果能成功拉取,说明守护进程代理配置正确。

Linux Systemd 服务的替代配置方法:

在某些 Linux 系统上,特别是使用 systemd 作为初始化系统时,你可以通过为 docker 服务创建 override 文件来设置环境变量,而不是直接修改 daemon.json。这种方法有时更适合自动化配置或与现有系统管理工具集成。

  1. 创建 override 目录:
    bash
    sudo systemctl edit docker.service

    这会打开一个编辑器,用于创建或编辑 /etc/systemd/system/docker.service.d/override.conf 文件。

  2. 添加环境变量:
    在文件中添加以下内容:
    conf
    [Service]
    Environment="HTTP_PROXY=http://your_proxy_server:port"
    Environment="HTTPS_PROXY=http://your_proxy_server:port"
    Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com"

    保存并关闭文件。

  3. 重新加载 systemd 配置并重启 Docker:
    bash
    sudo systemctl daemon-reload
    sudo systemctl restart docker

    这种方法通过环境变量的方式为 Docker 进程设置代理,效果与 daemon.json 类似,但优先级和具体行为可能略有差异(daemon.json 是 Docker 原生的配置方式,环境变量是继承自父进程或服务定义)。在大多数情况下,推荐使用 daemon.json,因为它更规范且与 docker info 输出一致。但如果你熟悉 systemd override 并且觉得更方便,也可以使用此方法。

方法二:配置 Build Time (构建时) 代理

构建时代理用于在 Dockerfile 中执行需要网络访问的命令。这不影响守护进程拉取基础镜像,只影响 RUN 等指令。

配置原理:

Dockerfile 构建过程默认不继承主机的环境变量,也不会自动使用守护进程的代理设置(除非你配置了自动传递构建参数)。你需要在构建过程中明确地将代理信息传递给构建环境。最安全和灵活的方式是使用 ARG--build-arg

配置步骤:

  1. 修改 Dockerfile:
    Dockerfile 的开头定义构建参数(Arguments):
    “`dockerfile
    # 定义代理参数
    ARG HTTP_PROXY
    ARG HTTPS_PROXY
    ARG NO_PROXY

    将构建参数转换为环境变量,供后续RUN指令使用

    这里的 ENV 指令会让这些变量在构建过程中生效,但不会保留在最终镜像中

    如果希望保留在最终镜像中,请使用 ENV 而非 ARG/ENV 组合,但不推荐用于敏感信息

    ENV http_proxy=$HTTP_PROXY
    ENV https_proxy=$HTTPS_PROXY
    ENV no_proxy=$NO_PROXY

    也可以使用小写形式,许多工具(如apt-get, curl)对大小写不敏感

    ENV http_proxy=$HTTP_PROXY

    ENV https_proxy=$HTTPS_PROXY

    ENV no_proxy=$NO_PROXY

    基础镜像

    FROM ubuntu:latest

    在这里执行需要网络访问的命令

    RUN apt-get update && apt-get install -y –no-install-recommends \
    curl \
    wget \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

    假设需要下载一个文件

    RUN curl -sSL http://example.com/somefile -o /app/somefile

    … 其他指令

    “`

    • ARG 指令定义了一个构建参数,可以在 docker build 命令中通过 --build-arg 传递值。
    • ENV 指令在构建环境中设置环境变量。我们将 ARG 接收到的值赋给 ENV,这样后续的 RUN 指令就能读取到这些代理环境变量。RUN 指令执行的命令通常会尊重 http_proxy/https_proxy/no_proxy 这些标准环境变量。注意,使用小写 http_proxy 是常见的约定,因为许多 shell 命令和库默认查找小写形式,但也建议同时设置大写形式以确保兼容性。
  2. 执行 docker build 命令并传递参数:
    在构建镜像时,使用 --build-arg 参数将代理地址传递给 Dockerfile:

    bash
    docker build \
    --build-arg HTTP_PROXY="http://your_proxy_server:port" \
    --build-arg HTTPS_PROXY="http://your_proxy_server:port" \
    --build-arg NO_PROXY="localhost,127.0.0.1,internal.example.com" \
    -t my_image .

    你可以根据需要只传递 HTTP_PROXYHTTPS_PROXYNO_PROXY 的语法与之前相同。

    带认证的代理:
    bash
    docker build \
    --build-arg HTTP_PROXY="http://username:password@your_proxy_server:port" \
    --build-arg HTTPS_PROXY="http://username:password@your_proxy_server:port" \
    -t my_image .

    同样,认证信息直接包含在 URL 中。请注意这种方式会将敏感信息暴露在构建命令历史记录中,并且需要在 Dockerfile 中使用 ARG 接收,这也不是最安全的方式。考虑使用 Docker BuildKit 的 Secret 功能来传递认证信息,但这超出了本基础教程的范围。

  3. (可选)配置守护进程自动传递构建参数 (Docker 17.07+):
    为了避免每次构建都手动输入 proxy 参数,你可以在 Docker 守护进程的 daemon.json 中配置让它自动将守护进程的代理设置作为构建参数传递给 Dockerfile。

    daemon.json 中添加或修改 build-args 字段:

    json
    {
    "httpProxy": "http://your_proxy_server:port",
    "httpsProxy": "http://your_proxy_server:port",
    "noProxy": "localhost,127.0.0.1,docker-registry.example.com,.corp",
    "build-args": {
    "HTTP_PROXY": "http://your_proxy_server:port",
    "HTTPS_PROXY": "http://your_proxy_server:port",
    "NO_PROXY": "localhost,127.0.0.1,docker-registry.example.com,.corp"
    }
    }

    请注意,build-args 中的值需要与 httpProxy, httpsProxy, noProxy 的值重复填写一遍。

    配置后,重启 Docker 守护进程。然后,你的 Dockerfile 只需要定义 ARG,构建时无需 --build-arg,Docker 会自动传递这些参数:

    “`dockerfile

    Dockerfile

    ARG HTTP_PROXY
    ARG HTTPS_PROXY
    ARG NO_PROXY

    ENV http_proxy=$HTTP_PROXY
    ENV https_proxy=$HTTPS_PROXY
    ENV no_proxy=$NO_PROXY

    FROM ubuntu:latest
    RUN apt-get update && apt-get install -y curl

    构建命令 (无需 –build-arg):

    docker build -t my_image .

    “`
    这个方法非常方便,推荐使用。

验证配置:

构建镜像成功本身就是一种验证。如果构建过程中需要网络访问的步骤通过了,说明构建时代理生效。你也可以在 Dockerfile 中添加一个简单的 RUN curl ipinfo.io 或访问一个特定网站的命令,然后在构建日志中查看请求是否通过代理(如果代理有日志功能)或是否成功。

方法三:配置 Runtime (运行时) 容器代理

运行时代理用于让容器内部运行的应用程序通过代理访问外部网络。这不影响拉取镜像或构建过程。

配置原理:

大多数应用程序会查找标准的 HTTP_PROXYHTTPS_PROXYNO_PROXY 环境变量来配置其网络访问。因此,最简单和通用的方法是在启动容器时为容器设置这些环境变量。

配置步骤:

  1. 使用 docker run 设置环境变量:
    docker run 命令中使用 -e 参数为容器设置代理相关的环境变量。

    bash
    docker run -d \
    -e HTTP_PROXY="http://your_proxy_server:port" \
    -e HTTPS_PROXY="http://your_proxy_server:port" \
    -e NO_PROXY="localhost,127.0.0.1,internal.example.com" \
    my_image your_command_here

    你可以同时设置大写和小写形式的环境变量,以确保兼容性:
    bash
    docker run -d \
    -e HTTP_PROXY="http://your_proxy_server:port" \
    -e HTTPS_PROXY="http://your_proxy_server:port" \
    -e NO_PROXY="localhost,127.0.0.1,internal.example.com" \
    -e http_proxy="http://your_proxy_server:port" \
    -e https_proxy="http://your_proxy_server:port" \
    -e no_proxy="localhost,127.0.0.1,internal.example.com" \
    my_image your_command_here

    带认证的代理:
    bash
    docker run -d \
    -e HTTP_PROXY="http://username:password@your_proxy_server:port" \
    -e HTTPS_PROXY="http://username:password@your_proxy_server:port" \
    my_image your_command_here

    与构建时类似,认证信息可以直接包含在 URL 中。这种方式的优势是敏感信息不会存储在镜像中,但会出现在 docker run 命令历史中。

  2. 使用 docker-compose 设置环境变量:
    docker-compose.yml 文件中,使用 environment 块为服务设置环境变量:

    “`yaml
    version: ‘3.8’

    services:
    app:
    image: my_image
    environment:
    – HTTP_PROXY=http://your_proxy_server:port
    – HTTPS_PROXY=http://your_proxy_server:port
    – NO_PROXY=localhost,127.0.0.1,internal.example.com
    # 也可以同时设置小写
    # – http_proxy=http://your_proxy_server:port
    # – https_proxy=http://your_proxy_server:port
    # – no_proxy=localhost,127.0.0.1,internal.example.com
    # … 其他配置
    “`

    然后使用 docker-compose up 启动服务。

验证配置:

启动容器后,可以通过以下方式验证:

  1. 进入容器查看环境变量:
    bash
    docker exec <container_id_or_name> env | grep -i proxy

    你应该能看到设置的代理相关的环境变量。

  2. 在容器内部测试网络访问:
    如果容器内部有 curlwget 等工具,可以进入容器执行命令测试:
    bash
    docker exec -it <container_id_or_name> /bin/bash # 或 sh
    # 在容器内部执行
    curl http://example.com
    curl https://google.com

    如果这些命令能够成功执行(通过代理),则说明运行时代理配置成功。如果访问 NO_PROXY 列表中的地址,应该直接连接而不是通过代理。

Docker Desktop 的代理配置

对于使用 Docker Desktop (Windows 或 macOS) 的用户,通常有一个更友好的图形界面来配置代理。

  1. 打开 Docker Desktop 设置。
  2. 导航到 “Resources” -> “Proxies”。
  3. 选择 “Manual proxy configuration”。
  4. 输入你的 HTTP 和/或 HTTPS 代理服务器地址和端口。
  5. 填写 “Bypass proxy for hosts” (即 NO_PROXY) 列表。
  6. 点击 “Apply & Restart”。

Docker Desktop 的这个设置会同时影响守护进程构建过程(通过自动传递构建参数)。它也会默认将这些代理设置作为环境变量注入到运行的容器中(除非容器自己覆盖了这些环境变量)。因此,使用 Docker Desktop UI 配置代理通常是最简单的方式,它会处理大部分场景。但对于需要精细控制(例如不同容器使用不同代理)或自动化部署的场景,手动修改 daemon.json、Dockerfile 和 docker run/docker-compose 命令仍然是必要的。

NO_PROXY 配置详解

NO_PROXY (或 noProxy) 是一个非常重要的设置,它指定了哪些主机名、IP 地址或域名不应该通过代理访问。正确配置 NO_PROXY 可以避免不必要的代理流量、提高内部资源访问速度,并解决访问内部服务时可能遇到的问题。

NO_PROXY 的值是一个逗号分隔的列表,可以包含:

  • IP 地址: 192.168.1.100
  • IP 地址段(CIDR 表示法): 192.168.0.0/24
  • 主机名: internal-service.local
  • 域名后缀: .corp.example.com (匹配该域名及其所有子域名)
  • 特殊值: localhost, 127.0.0.1 (通常应该包含,确保本地访问不走代理)
  • 空字符串: "" (表示所有地址都通过代理,除非是 localhost)

示例:

localhost,127.0.0.1,10.0.0.0/8,.internal.company.com

这个设置表示:
* 访问 localhost127.0.0.1 不走代理。
* 访问 10.x.x.x 网段内的所有 IP 地址不走代理。
* 访问以 .internal.company.com 结尾的所有主机名(包括 service.internal.company.comsub.service.internal.company.com)不走代理。

请注意,NO_PROXY 通常区分大小写,但一些实现(包括 Docker)可能会将其视为不区分大小写。为了最大兼容性,可以考虑同时设置大写和小写形式的环境变量 (NO_PROXYno_proxy)。

故障排除

如果在配置 Docker 代理后遇到问题,可以按照以下步骤进行排查:

  1. 检查代理服务器本身: 确保你提供的代理服务器地址和端口是正确的,并且代理服务器本身是正常工作的。尝试在宿主机上使用 curl -x http://your_proxy_server:port http://www.google.com 或浏览器配置代理来验证代理是否可用。
  2. 验证 Docker Daemon 配置:
    • 使用 docker info | grep -i proxy 检查代理设置是否成功应用到守护进程。
    • 检查 daemon.json 文件是否存在语法错误(JSON 格式)。
    • 确认已经重启了 Docker 守护进程。
  3. 验证构建时配置:
    • 检查 Dockerfile 中的 ARGENV 指令是否正确。
    • 如果手动使用 --build-arg,确认参数名称和值是否正确传递。
    • 如果依赖 daemon.json 自动传递,确认 daemon.json 中的 build-args 配置是否正确,并且守护进程已重启。
  4. 验证运行时配置:
    • 使用 docker exec <container_id> env | grep -i proxy 检查容器内部的环境变量是否正确设置。
    • 确认容器内部的应用程序是否正确读取并使用了这些环境变量(大多数标准库会这样做,但少数应用可能需要特定配置)。
    • 在容器内部执行网络命令测试(如 curl)。
  5. 检查 NO_PROXY 设置: 确保你要访问的地址不在 NO_PROXY 列表中,或者应该在的地址确实在列表中。特别是访问内网服务或 Docker 注册中心时。
  6. 防火墙问题: 检查宿主机或代理服务器的防火墙是否阻止了 Docker 访问代理服务器的端口。
  7. DNS 问题: 确保 Docker 环境能够解析代理服务器的主机名。如果使用主机名配置代理,尝试使用 IP 地址配置看看是否解决问题。容器内部也需要能够解析外部域名(可能需要配置容器的 DNS)。
  8. 认证问题: 如果代理需要认证,确认用户名和密码是否正确,格式是否符合要求。
  9. Docker 版本: 某些代理特性或自动传递构建参数的功能可能需要较新版本的 Docker。

总结

Docker 代理配置涉及三个主要场景:守护进程(拉取/推送镜像)、构建时(Dockerfile 中的网络命令)和运行时(容器内应用访问网络)。每个场景需要独立的配置方法:

  • 守护进程: 修改 daemon.json 文件并重启 Docker 服务。
  • 构建时: 在 Dockerfile 中使用 ARG/ENV 组合,并通过 docker build --build-arg 传递参数,或者配置 daemon.json 自动传递构建参数。
  • 运行时:docker run 命令或 docker-compose.yml 文件中使用 -e/environment 设置环境变量。

理解这三者的区别并根据实际需求进行配置是关键。对于使用 Docker Desktop 的用户,通常可以通过 UI 进行简化配置。在进行配置后,务必进行验证,并掌握基本的故障排除技巧。

正确配置 Docker 代理将帮助你在复杂的网络环境中顺畅地使用 Docker,从而专注于应用开发和部署,而非被网络问题困扰。希望这篇详细教程能帮助你成功配置 Docker 代理,穿越网络限制!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部