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

Docker Hub 拉取超时,先判断到底卡在哪一层 要点速览

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

采用 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 的连接列表里完全看不到 registry-1.docker.io、auth.docker.io 或相关 CDN 请求,第一顺位排查 Docker 是否配置了代理;如果能看到请求但被分到直连或疏漏策略组,再排查规则与节点。

第一口气:确认 Clash 本身真的可用 关键信息

如果返回 401 Unauthorized,反而多数现状下是好现象,说明请求已经到达 Docker Registry,只是匿名访问到到接口要求身份校验。

这里要多说一句:开始改 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 已经配置完成:

换个说法:若出现连接被拒绝,说明端口不对、Clash 没开启,或者该端口只提供 SOCKS5 而不是 HTTP。若命令长时间没有响应,再排查当前节点、Clash 日志和本机防火墙。

小技巧:不要只看「响应时间测试」结果。节点测速成功只说明测试 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 daemon 与 Clash 不在同一台机器上,127.0.0.1 就不能照抄。它只代表 Docker 所在机器自身,而不是你的 Windows 或 macOS 开发机。

如果 Docker 安装在 Linux 主机上,不妨采用 systemd drop-in 配置,而不是只在当前终端执行 export HTTPS_PROXY=...。

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

落到实处:后者只影响当前 Shell 开启的程序,对后台 Docker 服务没有作用。假设 Clash 的 HTTP 混合端口为 7890,得以创建 Docker 服务配置:

sudo systemctl show --property=Environment docker
docker info

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

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

Docker Desktop:配置引擎采用的代理(要点)

如果 Docker Desktop 无法连接到宿主机的 127.0.0.1,得以尝试 host.docker.internal;如果仍然无法完成,再在 Clash 开启 Allow LAN,并采用宿主机局域网 IP。设置完成后重启 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 菜单名称会变化,关键是确认代理设置作用于Docker Engine,而不是只填写了容器内部的环境变量。

docker info
docker pull hello-world

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

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

如果你的订阅采用规则集或脚本覆写,不要径直修改远端订阅原文件,因为下次升级或许把本地改动覆盖。

关键点是:Docker Hub 并不是只有一个域名。执行 docker pull nginx 时,Docker 多数现状下会先访问到到 Registry API,再访问到到身份校验服务,之后根据 manifest 获取实际镜像层。

域名或域名特征 普遍作用 排查关键点
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 官方 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 或直连规则之前。一个用于排查的最小写法如下,策略组名称要替换成你配置中真实存在的名称:

这里要多说一句:更稳妥的方式是在客户端的 Merge、Patch 或覆写功能中添加本地规则,并确认规则确实被合并到当前持续持续运行配置。修改后重新加载配置,再执行一次小镜像拉取,同时对照日志排查每个域名最终命中了哪个策略组。

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

第四步:排查 DNS、IPv6 与 TLS 握手困扰 要点速览

另外,Docker Hub 的身份校验和镜像下载均依赖 HTTPS。若系统时间严重疏漏、企业网络做了 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 功能。

请排查主机时间、Docker Desktop 的代理证书设置与系统证书链。不要为了「先拉下来」而关闭 TLS 验证,这会掩盖真正的证书困扰并减少镜像供应链的安全性。

第五步:用最小测试矩阵定位故障 关键信息

当你修改过 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 链路。