结论先说:Docker 的代理不是“一处设置、全部生效”。dockerd 拉取镜像、镜像构建过程、运行中的容器是三条不同链路;Docker Desktop 还有单独设置入口。应先定位失败发生在哪一层,再配置对应的 HTTP_PROXY、HTTPS_PROXY 与 NO_PROXY,并避免把代理凭据固化到镜像。
本文更新于 2026 年 8 月 24 日,面向已获得网络与目标系统授权的开发、测试和企业接入场景。软件版本、平台规则与供应商能力会变化,上线前请核对官方文档,并在测试环境完成回归。
Docker 三层代理配置对照
| 链路 | 典型动作 | 配置位置 | 验证方式 |
|---|---|---|---|
| Docker daemon | pull/push、访问镜像仓库 | daemon.json、服务环境或Desktop设置 | docker pull与daemon日志 |
| 镜像构建 | RUN apt/npm/curl | --build-arg或客户端代理配置 | plain progress与构建日志 |
| 运行中容器 | 应用访问外部API | --env、Compose env或运行时Secret | 容器内出口与应用日志 |
| Docker CLI配置 | 为新容器注入代理变量 | ~/.docker/config.json | docker inspect并检查脱敏结果 |
第一步:判断故障在 daemon、build 还是 runtime
docker pull 超时,通常看 daemon 到镜像仓库的链路;Dockerfile 中 RUN npm install 失败,看构建容器;镜像能构建但应用访问 API 失败,看运行中容器。三者进程、网络命名空间和配置来源不同。
先保留原始状态码和阶段日志,再做最小变更。不要因为容器内 curl 成功,就断言 daemon 已经配置;也不要因为 docker pull 成功,就认为应用会自动继承代理。
配置 daemon:Linux Engine 与 Docker Desktop 要分开
Docker Engine 官方推荐在 daemon.json 的 proxies 节配置 http-proxy、https-proxy 和 no-proxy,也支持为 systemd 服务设置环境变量。修改后要重新加载配置并重启服务,再用 systemctl show --property=Environment docker 检查生效值。
Docker 官方同时说明:Docker Desktop 会忽略 daemon.json 中这组代理配置,应通过 Desktop 设置管理。生产变更前先备份原配置,并确认 JSON 语法,避免因一个逗号导致 daemon 无法启动。
构建镜像:使用预定义代理参数,不把凭据写进 ENV
构建时可通过 --build-arg HTTP_PROXY=... 与 --build-arg HTTPS_PROXY=... 注入。Docker 对这些代理参数有预定义处理;不需要在 Dockerfile 中额外声明普通 ARG 才能使用。
docker build --progress=plain \
--build-arg HTTP_PROXY=http://proxy.example:8000 \
--build-arg HTTPS_PROXY=http://proxy.example:8000 \
--build-arg NO_PROXY=localhost,.internal.example .
不要用 Dockerfile 的 ENV 固化带凭据的代理地址。它会跟随镜像,并可能在检查或提交镜像时暴露。构建日志也应脱敏,公共 CI 更不能回显完整 URL。
运行容器:明确注入范围与 NO_PROXY
运行时可用 docker run --env HTTPS_PROXY=...,或在 Compose/编排平台中按服务注入。~/.docker/config.json 的代理配置会为新启动容器设置相关环境变量,但不会自动修改已经运行的容器。
NO_PROXY 至少评估容器服务名、内部域名、回环地址、私有网段和内部镜像仓库。不同工具对通配符与 CIDR 的支持并不完全一致,所以要用实际镜像中的 curl、包管理器和应用客户端分别验证。
故障排查与安全验收清单
- 分别执行拉取、构建、运行三项测试,记录失败层级。
- 验证代理协议与目标协议,不把“HTTPS 目标”误解为必须使用 HTTPS 代理入口。
- 遇到 407 检查凭据与白名单;遇到证书错误核对 CA 链,不关闭严格校验。
- 检查
docker inspect、构建日志和镜像历史中是否出现敏感值。 - 连续采样容器出口、TTFB 和错误率,并设置出口变化告警。
若只需要少数外部域名走固定出口,优先做精确分流;让全部容器流量长期经过同一代理,会扩大故障面,也会让内部请求绕远。
常见问题(FAQ)
docker pull 成功,为什么容器内还是无法联网?
pull 由 Docker daemon 发起,容器内请求由应用进程发起,两者不是同一配置层。
可以在 Dockerfile 里写 ENV HTTPS_PROXY 吗?
技术上可以,但会把配置保留在镜像环境中;如果包含凭据会产生泄露风险,不建议用于敏感代理。
修改 ~/.docker/config.json 后需要重启容器吗?
该配置主要影响新创建的容器。已有容器不会自动获得新变量,应按变更流程重建或重启并验证。
Docker Desktop 为什么不读取 daemon.json 的代理项?
Docker 官方明确说明 Desktop 的代理应通过 Desktop 设置管理,Engine 文档中的 daemon 配置不直接适用。
参考资料与延伸阅读
- Docker Docs:Daemon proxy configuration
- Docker Docs:Use a proxy server with the Docker CLI
- Docker Docs:Dockerfile predefined ARGs
站内相关阅读:代理IP协议选型指南、代理IP错误码与超时排查、按域名分流与故障回退。
