先定位失败发生在哪一层

失败位置真正发起请求的部分应检查的配置
docker pull 拉不下镜像Docker daemon 或对应构建后端Engine 守护进程 / Desktop 代理
Dockerfile 的 RUN 下载失败构建步骤所在环境构建代理参数、构建网络
容器启动后访问 API 失败容器内应用容器环境或应用自身代理
FROM 基础镜像下载失败构建器获取镜像构建器/daemon 出口,不只是 RUN 参数

先记录 Docker Desktop 还是原生 Docker Engine、版本、docker context show 的结果,以及失败的具体步骤。远程 context 或独立 BuildKit 的网络不一定在本机。不要因为本机 curl 成功,就推断远端守护进程也能连接 127.0.0.1。

第一层:镜像拉取走 daemon 或 Desktop 的设置

Docker Desktop 使用它自己的代理设置;官方文档明确指出 Desktop 会忽略 daemon.json 中的代理配置。原生 Docker Engine 则可按守护进程文档配置 daemon.json 或服务环境。先备份既有文件并合并 proxies 对象,不要覆盖其他存储、镜像和日志设置。下面演示的是支持这些字段的原生 Engine,不适用于 Desktop。

原生 Engine 的 daemon.json 片段;地址须能被 daemon 访问
{
  "proxies": {
    "http-proxy": "http://127.0.0.1:7890",
    "https-proxy": "http://127.0.0.1:7890",
    "no-proxy": "localhost,127.0.0.1"
  }
}

这里 https-proxy 的值仍可使用 http://,表示以 HTTP 代理建立 HTTPS 隧道,不表示把目标网站改成 HTTP。原生 Engine 的配置需按安装方式重启服务才生效;重启可能影响运行任务,应先保存工作并安排窗口。代理不在 daemon 所在主机时,127.0.0.1 必须更换。

第二层:构建步骤使用预定义代理参数

示意:替换成构建环境可到达的地址
docker build \
  --build-arg HTTP_PROXY=http://proxy.example.internal:7890 \
  --build-arg HTTPS_PROXY=http://proxy.example.internal:7890 \
  --build-arg NO_PROXY=localhost,127.0.0.1 \
  -t local/network-check .

proxy.example.internal 是占位地址,需换成真实可达的代理。Docker 提供的这些预定义参数无需在 Dockerfile 里额外声明。默认会从缓存和 docker history 中排除;若在 Dockerfile 中主动引用或打印它们,可能改变这一保护。不要用 ENV 把账号密码长期烘焙进镜像,也不要在排障日志里输出完整带凭据的代理 URL。

第三层:运行中容器的 localhost 是容器自己

Docker Desktop 可使用官方提供的 host.docker.internal 访问宿主服务,但服务的监听和防火墙仍须允许实际路径。原生 Linux Engine 不应默认假定这个名字可用,应按当前网络和 Engine 文档确认宿主入口。不要为了解决名字解析而给所有容器添加不必要的特权或 host 网络。

运行时可通过应用配置或 HTTP_PROXY、HTTPS_PROXY、NO_PROXY 等变量传入代理,但不是所有应用都采用相同变量规则。Docker 客户端的 ~/.docker/config.json 中 proxies 配置会给新容器和构建设置代理变量,不负责 Docker CLI 或 daemon 自身出站,也不会自动修改已运行的容器。

按三层分别验收与回退

  1. 先拉取一个体积适中的可信镜像,确认实际完成,区分网络错误、仓库认证错误和限流。
  2. 再运行原先失败的构建步骤,检查日志确实完成下载;缓存命中不能证明新配置的网络可用。
  3. 最后在目标容器里执行它本来要做的 API 或下载操作,确认应用自己使用了代理。不要只测宿主机浏览器。
  4. 失败时恢复对应层的旧配置,按需重启服务或重建容器,并撤销临时构建参数。持久数据留在原卷里,不需要删除全部镜像和数据卷。