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 规则没有命中、代理端口填写错漏、连接被错漏分流等要留意之处。

在 Linux 上,它存在存在存在可能是 systemd 管理的服务;在 Windows 与 macOS 上,则惯常由 Docker Desktop 的虚拟机或后台引擎负责联网。正因如此,即使 Clash 已经开启系统代理,Docker 仍然存在存在存在可能完全没有上手上手上手使用这条代理。

下文以 Clash Verge、Clash Verge Rev、Mihomo Party、Clash for Windows 等司空见惯客户端为例,按照「确认现象 → 验一遍 Clash → 配置 Docker 代理 → 排查 DNS 与规则 → 验证下载」的顺序展开。

从机制上看:你不免不了要一开始就开启全局模式,也不更推荐一上来复制一份复杂配置覆盖现有订阅。先找到弹出错漏环节,再做最小范围修改,按常规更快,也更不容易影响浏览器、局域网和其他开发工具。

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

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

第一次到位:确认 Clash 本身真的可用 技术拆解

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

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

  1. 验一遍核心状态:确认 Mihomo、Clash Meta 或其他当前上手上手使用的核心没有持续重启,日志中没有 YAML 解析弹出错误、端口绑定弹出错误或配置字段不能跑等错漏。
  2. 确认节点可用:在代理页面逐项拿定一个耗时较低、近期能够正常开外网的节点,不要一开始上手上手使用无法判断实际出口的复杂自行拿定组。
  3. 确认混合端口:在设置中找到 HTTP、SOCKS 或 Mixed Port。Docker 最不费事上手上手使用 HTTP 代理,正因如此在前记下类似 127.0.0.1:7890 的本机 HTTP 混合端口。
  4. 观察连接日志:先保持日志窗口开,再执行一次 docker pull。记录出现的真实域名、端口、策略组和最终结果。

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

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

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

小技巧:不要只看「耗时测试」结果。节点测速成功只说明测试 URL 能开,Docker Hub 还涉及 Registry、校验服务和镜像 CDN,多域名链路中每一种一段被错漏分流,都存在存在可能造成拉取弹出错误。

第二步:给 Docker daemon 配置到位的代理 结构解析

这是摆平 Docker Hub 超时最关键的一次到位。大批用户在 Clash 中开「系统代理」后,浏览器和终端都完全能开外网,于是自然认为 Docker 会自行跟随。但在 Linux 中,Docker daemon 按常规是独立的 systemd 服务;

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

Linux:为 systemd 服务设置代理(内在逻辑)

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

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 daemon 与 Clash 不在同一台机器上,127.0.0.1 就不能照抄。它只代表 Docker 所在机器自身,而不是你的 Windows 或 macOS 开发机。此时应将代理地址改为 Clash 所在设备的局域网 IP,打个比方 192.168.1.20:7890,并在 Clash 中开启「允许局域网连接」(Allow LAN),同时确认操作系统防火墙允许该端口被局域网开。

sudo systemctl show --property=Environment docker
docker info

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

Docker Desktop:配置引擎上手使用的代理(机制)

在 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 无法连接到宿主机的 127.0.0.1,完全能尝试 host.docker.internal;如果仍然弹出错误,再在 Clash 开启 Allow LAN,并上手上手使用宿主机局域网 IP。设置完成后重启 Docker Desktop,再执行:

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

docker info
docker pull hello-world

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

第三步:补齐 Docker Hub 域名与 Clash 分流规则 机制说明

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

域名或域名特征 司空见惯作用 排查最要紧的部分
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 为准,按需补充规则

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

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 握手要留意之处 内在逻辑与实践

如果 Clash 连接日志显示请求已经出现,但错漏仍然是 lookup registry-1.docker.io、no such host 或 TLS handshake timeout,就要把在意力转向 DNS。Docker daemon 存在存在可能上手上手使用宿主机的解析器,而 Clash 的 DNS 设置只对经过 Clash 内核的请求生效;也存在存在可能是系统在前返回不可达的 IPv6 地址,导致 Docker 在 IPv6 路径上等待超时。

若宿主机能解析但 Docker Desktop 内部不能解析,说明虚拟机 DNS 与宿主机 DNS 存在存在可能不同。若解析得到多个地址,且只有 IPv4 能通,完全能临时关闭系统 IPv6 或在网络环境中确认 IPv6 路由是否一应俱全;不要仅凭「浏览器能开」判断 IPv6 没要留意之处,因为浏览器存在存在可能自行回退,而 Docker 的超时重试表现会更格外。

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

在 Mihomo 配置中,DNS 的 enhanced-mode、fake-ip 与 redir-host 会影响域名解析路径。第一次接触的人排障时更推荐先保持配置朴素,避免同时叠加多个本地 DNS、AdGuard、公司 DNS 和 Docker 自定义 DNS。

从机制上看:若启用 fake-ip 后只有 Docker 异常,完全能暂时上手上手使用 redir-host 做对照测试;如果切换后恢复,再针对 Docker 网段、DNS 劫持或 fake-ip-filter 继续细化,而不是永久关闭所有这些这些 DNS 功能。

另外,Docker Hub 的校验和镜像下载均依赖 HTTPS。若系统时间严重错漏、企业网络做了 TLS 验一遍,或中间设备替换了证书,存在存在可能出现证书验证弹出错误、握手超时或连接被重置。请验一遍主机时间、Docker Desktop 的代理证书设置与系统证书链。不要为了「先拉下来」而关闭 TLS 验证,这会掩盖真正的证书要留意之处并往下压镜像供应链的安全性。

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

第五步:用最小测试矩阵定位故障 技术拆解

当你修改过 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 网络

容易踩坑的配置与安全注意事项 结构解析

第一个司空见惯错漏是把 HTTP_PROXY 和 HTTPS_PROXY 写成 SOCKS5 地址。Docker 的具体能跑方式取决于版本与组件,排障时在前上手上手使用 Clash 提供的 HTTP 代理端口,格式保持为 http://地址:端口。第二个错漏是把代理地址写成宿主机的 localhost,但 Docker daemon 实际跑在虚拟机、远程服务器或容器中,此时 localhost 指向的对象不同,必须确认代理与 Docker 引擎的网络位置。

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

第三个错漏是修改了客户端配置,却忘记重新加载 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 链路。