Docker Hub 拉取镜像超时?用 Clash 这样排查处理

Docker Hub 拉取超时,先判断到底卡在哪一层 一文看懂

你不得一开始就开启全局模式,也不推荐干脆复制一份复杂配置覆盖现有订阅。先找到不成功环节,再做最小范围修改,一般更快,也更不容易影响浏览器、局域网和其他开发工具。

运用 Docker pull 拉取镜像时,最为普遍的提示涵盖 i/o timeout、context deadline exceeded、Client.Timeout exceeded while awaiting headers、net/http: TLS handshake timeout,以及反复出现 dial tcp: lookup registry-1.docker.io。这些失误看起来都像「Docker Hub 被墙」或「节点太慢」,但实际也许分别对应域名解析不成功、Docker 守护进程没有走代理、Clash 规则没有命中、代理端口填写失误、连接被失误分流等难点。

尤其要留意,Docker 命令行和 Docker Desktop 的网络路径并不总是等同于浏览器。浏览器开启网页正常,只能证明浏览器运用的代理链路可用;docker pull 一般由后台跑起来的 Docker daemon 发起请求。

先看这一点:在 Linux 上,它也许是 systemd 管理的服务;在 Windows 与 macOS 上,则通常由 Docker Desktop 的虚拟机或后台引擎负责联网。所以,即使 Clash 已经开启系统代理,Docker 仍然也许完全没有运用这条代理。

这篇文章以 Clash Verge、Clash Verge Rev、Mihomo Party、Clash for Windows 等高频客户端为例,按照「确认现象 → 核对 Clash → 配置 Docker 代理 → 排查 DNS 与规则 → 验证下载」的顺序展开。

先记住一个判断:如果 Clash 的连接列表里完全看不到 registry-1.docker.io、auth.docker.io 或相关 CDN 请求,首位核对 Docker 是否配置了代理;如果能看到请求但被分到直连或失误策略组,再核对规则与节点。

第一气:确认 Clash 本身真的可用 核心要点

如果返回 401 Unauthorized,反而通常是好现象,说明请求已经到达 Docker Registry,只是匿名连通接口要求鉴权。若出现连接被拒绝,说明端口不对、Clash 没拉起,或者该端口只提供 SOCKS5 而不是 HTTP。若命令长时间没有响应,再核对当前节点、Clash 日志和本机防火墙。

开始改 Docker 配置前,先在 Clash 客户端中确认当前配置文件已经成功加载,并且代理核心处于跑起来状态。对于 Clash Verge Rev 或 Mihomo Party,一般能够在「配置」「Profiles」或类似页面看到当前激活的 YAML;

  1. 核对核心状态:确认 Mihomo、Clash Meta 或其他当前运用的核心没有持续重启,日志中没有 YAML 解析不成功、端口绑定不成功或配置字段不兼容等失误。
  2. 确认节点可用:在代理页面手工挑选一个时延较低、近期能够正常连通外网的节点,不要一开始运用无法判断实际出口的复杂无人值守挑选组。
  3. 确认混合端口:在设置中找到 HTTP、SOCKS 或 Mixed Port。Docker 最省事运用 HTTP 代理,所以首位记下类似 127.0.0.1:7890 的本机 HTTP 混合端口。
  4. 观察连接日志:先保持日志窗口开启,再执行一次 docker pull。记录出现的真实域名、端口、策略组和最终结果。

补充说明:对于 Clash for Windows,则要核对 Profiles 页面是否存在可用配置。配置文件如果没有激活,或者订阅已经过期,系统代理开关即使显示为开启,也不代表有可用的出站节点。

curl -I -x http://127.0.0.1:7890 https://registry-1.docker.io/v2/

能够先用终端验证 Clash 的 HTTP 端口是否工作。下面的命令只测试代理本身,不代表 Docker daemon 已经配置完成:

小技巧:不要只看「时延测试」结果。节点测速成功只说明测试 URL 能连通,Docker Hub 还涉及 Registry、鉴权服务和镜像 CDN,多域名链路中无论哪种一段被失误分流,都也许造成拉取不成功。

第二步:给 Docker daemon 配置无误的代理 逐条拆解

这是处理 Docker Hub 超时最关键的一气。不少运用者在 Clash 中开启「系统代理」后,浏览器和终端都能够连通外网,于是自然认为 Docker 会无人值守跟随。但在 Linux 中,Docker daemon 通常是独立的 systemd 服务;

它不会读取你当前 Shell 里的代理变量,也不会无人值守继承桌面客户端的系统代理设置。Windows 和 macOS 的 Docker Desktop 也有独立的引擎网络设置,得在 Docker Desktop 的代理页面中单独配置。

Linux:为 systemd 服务设置代理(一眼看懂)

此时应将代理地址改为 Clash 所在设备的局域网 IP,比如 192.168.1.20:7890,并在 Clash 中开启「允许局域网连接」(Allow LAN),同时确认操作系统防火墙允许该端口被局域网连通。

sudo mkdir -p /etc/systemd/system/docker.service.d

sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:7890"
Environment="HTTPS_PROXY=http://127.0.0.1:7890"
Environment="NO_PROXY=localhost,127.0.0.1,::1"
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

换个角度:如果 Docker 安装在 Linux 主机上,推荐运用 systemd drop-in 配置,而不是只在当前终端执行 export HTTPS_PROXY=...。后者只影响当前 Shell 拉起的程序,对后台 Docker 服务没有作用。假设 Clash 的 HTTP 混合端口为 7890,能够创建 Docker 服务配置:

sudo systemctl show --property=Environment docker
docker info

重启之后不要立即重复拉取大型镜像,先确认服务确实读取到环境变量:

如果 Docker daemon 与 Clash 不在同一台机器上,127.0.0.1 就不能照抄。它只代表 Docker 所在机器自身,而不是你的 Windows 或 macOS 开发机。

Docker Desktop:配置引擎运用的代理(核心)

hello-world 镜像体积很小,适合验证 Registry 鉴权与基础下载链路。测试成功后,再拉取 Node、Python 或 CUDA 等大型镜像,否则下载数 GB 文件时即使只剩 CDN 连接难点,也会让排障过程变得很慢。

具体来说:在 Windows 或 macOS 上,Docker Desktop 也许跑起来在独立的 Linux 虚拟环境中。请开启 Docker Desktop 的 Settings,找到 Resources、Proxies 或 Network 中与代理相关的页面,将 HTTP Proxy 和 HTTPS Proxy 指向 Clash 的 HTTP 端口,比如 http://host.docker.internal:7890 或 Docker Desktop 能够连通到的宿主机地址。

不同版本的 Docker Desktop 菜单名称会变化,关键是确认代理设置作用于Docker Engine,而不是只填写了容器内部的环境变量。

docker info
docker pull hello-world

如果 Docker Desktop 无法连接到宿主机的 127.0.0.1,能够尝试 host.docker.internal;如果仍然不成功,再在 Clash 开启 Allow LAN,并运用宿主机局域网 IP。设置完成后重启 Docker Desktop,再执行:

第三步:补齐 Docker Hub 域名与 Clash 分流规则 底层逻辑

如果你的订阅运用规则集或脚本覆写,不要干脆修改远端订阅原文件,因为下次刷新也许把本地改动覆盖。更稳妥的方式是在客户端的 Merge、Patch 或覆写功能中添加本地规则,并确认规则确实被合并到当前跑起来配置。修改后重新加载配置,再执行一次小镜像拉取,同时对照日志核对每个域名最终命中了哪个策略组。

域名或域名特征 高频作用 排查要点
registry-1.docker.io Registry API 与镜像清单请求 确认没有被失误直连,观察是否返回 401 或正常 TLS
auth.docker.io 镜像仓库鉴权与 Token 获取 鉴权域名无法连通时,高频表现是 pull 卡在登录或获取 token
docker.io 用户输入的镜像仓库名称与相关跳转 不能只依赖这一条规则覆盖全部实际请求
production.cloudflare.docker.com 部分镜像层下载运用的 CDN 域名 元数据成功但 layer 下载超时,应要点查看该类连接
日志中出现的其他 CDN 镜像层或重定向后的分发地址 以 Clash 连接日志中的真实 SNI 为准,按需补充规则

顺带一提:Docker Hub 并不是只有一个域名。执行 docker pull nginx 时,Docker 通常会先连通 Registry API,再连通鉴权服务,之后根据 manifest 获取实际镜像层。镜像层也许来自 Docker 官方 CDN 或由响应返回的其他分发域名。只把 docker.io 写进规则并不一定充分,因为实际连接中也许出现 registry-1.docker.io、auth.docker.io、production.cloudflare.docker.com 等主机名。

rules:
  - DOMAIN,registry-1.docker.io,Proxy
  - DOMAIN,auth.docker.io,Proxy
  - DOMAIN-SUFFIX,docker.io,Proxy
  - DOMAIN-SUFFIX,docker.com,Proxy
  - DOMAIN,production.cloudflare.docker.com,Proxy

规则顺序同样关键。Docker Hub 规则应放在过于宽泛的 GEOIP、MATCH 或直连规则之前。一个用于排查的最小写法如下,策略组名称得替换成你配置中真实存在的名称:

不要盲目把所有流量设为全局:全局模式能够作为短时间的诊断手段,但它会改变 Git、内网服务、公司域名和其他开发工具的网络路径。确认 Docker Hub 在全局模式下恢复后,应回到规则模式,逐条补齐实际命中的 Docker 域名。

第四步:排查 DNS、IPv6 与 TLS 握手难点 一文看懂

另外,Docker Hub 的鉴权和镜像下载均依赖 HTTPS。若系统时间严重失误、企业网络做了 TLS 核对,或中间设备替换了证书,也许出现证书验证不成功、握手超时或连接被重置。请核对主机时间、Docker Desktop 的代理证书设置与系统证书链。不要为了「先拉下来」而关闭 TLS 验证,这会掩盖真正的证书难点并压低镜像供应链的安全性。

如果 Clash 连接日志显示请求已经出现,但失误仍然是 lookup registry-1.docker.io、no such host 或 TLS handshake timeout,就要把留意力转向 DNS。

先看这一点:Docker daemon 也许运用宿主机的解析器,而 Clash 的 DNS 设置只对经过 Clash 内核的请求生效;也也许是系统首位返回不可达的 IPv6 地址,导致 Docker 在 IPv6 路径上等待超时。

getent hosts registry-1.docker.io
curl -I https://registry-1.docker.io/v2/
docker pull hello-world

先在 Docker 所在环境中分别测试解析结果与 HTTPS 连接:

若宿主机能解析但 Docker Desktop 内部不能解析,说明虚拟机 DNS 与宿主机 DNS 也许不同。若解析得到多个地址,且只有 IPv4 能通,能够临时关闭系统 IPv6 或在网络环境中确认 IPv6 路由是否齐全;不要仅凭「浏览器能开启」判断 IPv6 没难点,因为浏览器也许无人值守回退,而 Docker 的超时重试表现会更显著。

补充说明:在 Mihomo 配置中,DNS 的 enhanced-mode、fake-ip 与 redir-host 会影响域名解析路径。初学者排障时推荐先保持配置容易,避免同时叠加多个本地 DNS、AdGuard、公司 DNS 和 Docker 自定义 DNS。

若启用 fake-ip 后只有 Docker 异常,能够暂时运用 redir-host 做对照测试;如果切换后恢复,再针对 Docker 网段、DNS 劫持或 fake-ip-filter 继续细化,而不是永久关闭全部 DNS 功能。

第五步:用最小测试矩阵定位故障 核心要点

当你修改过 Clash、Docker 代理和 DNS 后,最好按固定顺序测试,而不是连续执行几十次同一个 docker pull。每一气都应记录结果,这样能够判断故障是出在代理端口、Docker daemon,还是某个具体镜像仓库。

  1. 测试代理端口:运用 curl -x 请求 https://registry-1.docker.io/v2/,确认 HTTP 混合端口能建立 TLS 并得到 401 或其他明确响应。
  2. 测试 Docker 引擎:执行 docker info,确认客户端连接的是预期的 Docker daemon,而不是远程环境或失误的 Docker Context。
  3. 测试小镜像:先执行 docker pull hello-world 或其他体积较小的公共镜像,避免大文件下载掩盖连接难点。
  4. 测试指定版本:运用 docker pull nginx:stable 这类固定标签,排除 latest 标签变化或镜像清单差异造成的误判。
  5. 对照连接日志:确认 Registry、鉴权服务和 CDN 请求是否都经过同一个可用策略组;如果中途切换节点,先固定单个节点复测。
  6. 最后测试大镜像:小镜像稳健后再拉取 Node、Python、Ubuntu 或其他大型镜像,并观察是否只在某个 layer 下载阶段不成功。

能够用下面的表格高速对照现象:

现象 首位怀疑 处理方向
Clash 日志没有无论哪种 Docker 域名 Docker daemon 未运用代理 核对 systemd、Docker Desktop 或远程 Docker 引擎代理
Registry 返回 401,但 pull 仍不成功 鉴权域名或 CDN 未分流 查看 auth.docker.io 与 layer 下载域名
解析不成功或 no such host DNS 路径不一致 相当宿主机、Docker 引擎和 Clash 的解析结果
小镜像成功,大镜像中途超时 CDN、节点稳健性或连接复用难点 固定节点,核对 CDN 规则并更换低抖动出口
只有 IPv6 地址连接不成功 IPv6 路由或防火墙不齐全 临时对照 IPv4,之后再修复 IPv6 网络

容易踩坑的配置与安全注意事项 逐条拆解

安全方面,Docker Hub 账号密码、连通令牌和私有仓库地址都不应写进公开的 Clash 配置或命令历史。公共镜像拉取成功后,仍推荐固定镜像版本、核对镜像来源,并在生产环境中运用可信的私有镜像仓库或镜像缓存。代理配置只处理网络可达性,不会替你验证镜像是否安全,也不会替代容器镜像扫描和供应链审计。

换个角度:第一个高频失误是把 HTTP_PROXY 和 HTTPS_PROXY 写成 SOCKS5 地址。Docker 的具体兼容方式取决于版本与组件,排障时首位运用 Clash 提供的 HTTP 代理端口,格式保持为 http://地址:端口。

第二个失误是把代理地址写成宿主机的 localhost,但 Docker daemon 实际跑起来在虚拟机、远程服务器或容器中,此时 localhost 指向的对象不同,必须确认代理与 Docker 引擎的网络位置。

第三个失误是修改了客户端配置,却忘记重新加载 Profile;或者已经加载新配置,但 Docker Desktop 仍缓存旧的代理设置,没有重启引擎。第四个失误是只添加 docker.io,不看连接日志中的鉴权与 CDN 域名。第五个失误是反复切换节点,却没有固定变量,导致每次测试结果都不同,最后无法判断到底是规则修好了,还是某个节点偶然恢复。

高频难点 底层逻辑

开启 Clash 系统代理后,为什么浏览器能用而 Docker 不能用?(逐条)

因为浏览器通常遵循桌面系统代理,而 Docker pull 由后台 Docker daemon 发起。Linux daemon 得通过 systemd 环境变量配置代理;Docker Desktop 则得在其引擎或代理设置中填写宿主机可连通的 HTTP 代理地址。两者都不能仅凭浏览器开启网页来判断。

连通 registry-1.docker.io 返回 401,是不是代理不成功?(机制)

不一定。Registry 的 /v2/ 接口对未鉴权请求返回 401 很高频,这说明 HTTPS 请求也许已经成功到达服务端。接下来应核对 auth.docker.io 是否能够获取 Token,并观察实际镜像层下载时运用的 CDN 域名。

处理 Docker Hub 超时必须开启 TUN 模式吗?(一眼看懂)

不必须。如果 Docker daemon 已无误运用 Clash 的 HTTP 代理,规则模式通常就充分。TUN 更适合无法单独配置代理、得接管大批系统流量的状态,但开启后会增加路由、DNS、虚拟网卡和局域网连通的变量。推荐先用显式 Docker 代理完成验证,再决定是否得 TUN。

小镜像能拉取,大镜像仍然超时,应当怎么办?(核心)

要点查看大镜像不成功时的真实连接域名和 layer 下载阶段。固定一个稳健节点,确认 CDN 域名没有被直连或失误分流,并核对 Docker Desktop、宿主机与 Clash 的超时设置。如果只有单个镜像或单个 layer 不成功,也要考虑镜像仓库侧的临时故障,而不是继续修改全局 DNS。

相比只会一键切换全局代理的同类工具,部分方案对 Docker daemon、虚拟机网络和 CDN 分流的边界说明并不清楚,遇到「浏览器能用、镜像仍超时」时通常只能反复换节点;Clash 更适合这种得看日志、核对端口、区分 Docker Desktop 与 Linux 服务并逐条维护规则的情况,这篇文章的排查路径也能和客户端的连接记录对应起来。若你希望先准备一个兼容规则分流、TUN 与混合端口配置的 Clash 客户端,不妨前往下载,再按这篇文章的最小测试矩阵逐步验证 Docker Hub 链路。