先判断超时发生在哪一层:Docker、Clash 还是网络

执行 docker pull 时,终端只是向本机 Docker Engine 发送请求;真正连接 Docker Hub 的通常是后台的 Docker daemon,而不是当前 Shell 里的命令进程。这是排查「浏览器能打开网页,Docker Hub 镜像却拉不下来」时最容易忽略的区别:你在终端设置了 HTTPS_PROXY,不代表后台 daemon 也会读取它。桌面端还多一层客户端与虚拟机,命令行所在环境、Docker Desktop 虚拟机和宿主机代理设置也可能不一致。

先记下完整报错和发生时间,再判断卡在哪个阶段。若提示解析域名失败,优先看 DNS;若一直停在 Pulling fs layer 或下载某个 layer 时超时,可能是 registry 认证、镜像数据 CDN 或代理连接问题;若立即出现连接拒绝,则检查 Clash 端口、daemon 代理地址和防火墙。Docker Hub 登录成功也不代表镜像层下载必然成功,因为登录、获取清单和下载 layer 可能访问不同主机。

还要把「慢」与「失败」分开记录。单个大 layer 下载缓慢,可能是节点带宽或服务商限速;所有请求都在建立连接前卡住,更像代理没有生效;只有特定镜像失败,则可能与镜像名称、平台架构、标签是否存在或 Hub 的匿名拉取限额有关。一次只改变一个变量,才能从结果判断真正原因,而不是反复换节点、改 DNS 后无法确认哪项修复有效。

ℹ 先记住这一点:docker pull 的网络请求通常由 Docker daemon 发出。仅在当前终端设置代理变量,不能作为 daemon 已走 Clash 的证据;必须检查 daemon 或 Docker Desktop 自己的代理配置。

检查 Clash 节点、运行状态与代理模式

先确认 Clash 客户端核心正在运行,当前配置已启用,并且策略组里选中的不是失效节点。用浏览器打开普通网站只能证明浏览器路径可用,不足以证明 Docker 使用了相同代理。可以先在 Clash Verge、Clash Verge Rev 或其他 Mihomo 客户端中查看连接面板与日志,准备执行一次拉取时,观察是否出现 docker.io、auth.docker.io 或相关下载主机的连接记录。不同客户端的菜单名称可能略有差异,但目标是确认请求是否到达内核、命中了什么规则、最后选了哪个出站。

排查时先使用规则模式,并暂时把 Docker Hub 相关请求明确交给一个可用的代理策略组。若你不确定现有规则是否命中,可以短时间切到全局模式做对照测试;全局模式成功、规则模式失败,说明问题更可能在规则匹配或策略组选择,而不是 Docker 镜像本身。测试完成后应恢复日常模式,不要把全局代理当作长期修复方案,否则其他本应直连的流量也会被送入代理。

日志里重点看连接的目标域名、规则类型、策略组和出站节点。若出现请求但走了 DIRECT,说明规则没有按预期覆盖该域名;若连接进入代理组但节点握手失败,则继续检查节点可用性、服务器时间、TLS 错误和网络限制。若日志完全没有相关条目,优先考虑 Docker daemon 没有使用 Clash 的代理端口,或请求被 Docker Desktop 的虚拟网络、系统防火墙等环节阻断。

还需区分 Clash 的代理端口类型。Docker Engine 的 HTTP(S) 代理配置通常需要 HTTP 代理入口;Mihomo 配置中的 mixed-port 可以接收常见 HTTP 与 SOCKS 客户端连接,单独的 socks-port 则不是 HTTP 代理。不要把 SOCKS 端口误填成 Docker 的 HTTP 代理地址,然后仅凭「端口正在监听」判断配置正确。端口号以你当前配置为准,不要假设所有安装默认使用同一个数字。

让 Docker daemon 正确使用 Clash 代理

在 Linux 上,先确认 Docker Engine 实际运行位置与 Clash 监听地址。若两者都在同一台主机,可将 daemon 的 HTTP 和 HTTPS 代理指向本机 Clash 的 HTTP 兼容入口。下面是配置结构示例,地址与端口必须替换为你自己的值;不要直接复制后就假定立即生效。Docker Engine 版本、发行版和启动方式可能影响配置来源,修改前先备份已有设置,避免覆盖现存的私有仓库、证书或其他代理参数。

Docker 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,.内部域名"
  }
}

修改配置后,按当前系统的运维流程重启 Docker daemon,并检查服务是否成功启动。若 Docker 无法启动,不要继续改多处设置;先查看 daemon 日志和 JSON 语法,尤其核对逗号、引号与配置文件位置。使用 systemd 的环境变量代理方案时,要把代理设置写到 Docker 服务对应的环境中,再执行 daemon 重载与服务重启;只在个人 Shell 配置文件中添加变量不会自动传给系统服务。

当 Clash 与 Docker daemon 不在同一网络命名空间时,127.0.0.1 未必指向宿主机。例如 Docker Desktop 的 daemon 运行在虚拟化环境中,容器、虚拟机和宿主机各自的回环地址并不相同。优先使用 Docker Desktop 设置中的代理入口,并确认客户端显示代理已应用;手工填入宿主机地址时,必须保证虚拟机能够访问该地址,而且 Clash 监听范围和防火墙规则允许必要连接。不要为了测试就把代理监听无条件暴露到公网。

Windows 与 macOS 用户尤其要检查代理究竟配置在 Docker Desktop 的哪个位置。宿主机系统代理生效,不等同于 Desktop 后台引擎已经使用该代理;在客户端设置页保存后,按提示重启 Desktop,再检查状态和连接日志。若使用 WSL、远程 Docker context 或 SSH 连接另一台 Linux 主机,本地 Clash 的设置也不会自动传到远程 daemon,应在真正执行拉取的那台主机或对应 Docker 环境配置代理。

no-proxy 用于列出不应经代理访问的目标,例如本机服务或单位内部域名。不要把 Docker Hub 域名误放进排除列表,否则 daemon 可能绕过 Clash 直连;也不要随意设置一个过宽的排除后缀,造成需要代理的请求落回失败路径。保存后逐项核对生效配置,并通过实际拉取验证,而不是只依据配置文件已经写入就认定完成。

核对 Docker Hub 域名与 Clash 规则命中

Docker Hub 拉取并非只连一个固定主机。常见流程可能涉及 registry-1.docker.io 获取镜像清单、auth.docker.io 获取授权令牌,以及承载镜像层内容的下载域名。实际主机可能随 Hub 后端和 CDN 调整而变化,因此不要把一份长期不更新的域名清单当作完整答案。更稳妥的办法是先触发一次失败的拉取,再对照 Clash 连接记录中的实际目标补充规则。

如果你维护自己的规则,可以先将 Docker Hub 相关的明确域名交给同一个代理策略组,方便观察和管理。域名规则应尽量精确,避免用过宽的关键词规则误把无关服务也送进代理。规则添加后检查顺序:若前面已有更宽泛的直连规则,后面的代理规则可能永远不会被执行。此时需要调整规则优先级,或检查规则集是否在配置更新时被覆写。

对照日志时,不要只看连接是否出现,还要看最终命中的规则和出站。请求落到正确策略组但拉取仍失败,说明接下来应检查节点、认证、出口限制或 layer 下载路径;请求没有命中预期规则,则优先修规则顺序和域名范围。对于新出现的 CDN 主机,应先从当前连接日志和 Docker 报错中确认,再决定是否加入策略,避免凭猜测添加大量不相关域名。

你也可以短暂使用全局模式来验证「规则分流」是不是问题来源。若全局模式可用,而规则模式始终失败,记下日志里实际访问的主机并回到规则模式修正;若两种模式都失败,则继续检查代理端口是否能从 daemon 所在环境访问,以及当前节点能否建立 HTTPS 连接。对比时确保使用相同镜像、相同网络和同一时间段,减少 Hub 状态变化带来的干扰。

用 DNS 与命令行测试缩小问题范围

DNS 故障常见表现包括域名解析失败、解析结果明显不稳定,或者代理日志里一直看不到请求。先从执行命令的主机检查域名是否可以解析,再观察 Clash 的 DNS 设置和连接日志。需要注意的是,检查宿主机能解析域名,不一定证明远程 Docker daemon 或 Docker Desktop 虚拟机使用相同 DNS;反过来,如果 Docker daemon 通过 HTTP 代理发出请求,部分域名解析可能由代理侧完成,单独改变宿主机 DNS 也未必能修复链路。

基础连通性对照命令

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

对 Docker Registry 的 /v2/ 入口,返回 401 Unauthorized 在未认证时可能是正常响应:它说明请求到达了服务端并收到了认证挑战,并不等于网络错误。判断时关注是否完成 DNS、TCP 与 TLS 建连,是否出现连接超时或证书错误。第二条命令测试当前主机的直接请求,第三条命令测试显式指定代理后的请求;如果系统没有安装 curl,或该版本不支持相关参数,可使用等价的 HTTP 客户端工具。

这组测试不能代替 Docker daemon 的实际验证,因为命令行 curl 和 Docker daemon 是不同进程,可能使用不同代理设置、证书存储和网络命名空间。若代理测试成功但拉取失败,回到 daemon 或 Docker Desktop 的代理配置;若代理测试也超时,再检查 Clash 节点、策略组出站、DNS 与本机防火墙。不要在尚未确认故障点前同时切换多个 DNS 服务或清空所有缓存,否则诊断依据会被抹掉。

DNS 规则调整时,应先确认配置中的 DNS 模式、上游服务器和 fake-IP 或 redir-host 行为符合当前客户端使用方式。不要因为 Docker Hub 域名解析结果与预期不同,就直接把所有域名强制指向某个 IP:CDN 地址可能变化,固定地址会带来新的 TLS、可用性和地域问题。更应确认解析请求由谁处理、解析后的连接是否按规则走代理,以及 Clash 日志是否给出明确的解析错误。

重新拉取验证与常见问题

修复后先用一个公开、体积较小且标签明确的镜像做验证,避免一开始就用大型镜像把带宽、磁盘空间、Hub 限额和代理问题混在一起。执行拉取时同时观察 Docker 输出、Clash 连接面板和 daemon 日志。若小镜像成功,再尝试原先失败的目标;若只在匿名拉取时失败,可登录 Docker Hub 后复测,并留意认证错误、拉取频率限制和账户状态。登录成功只能证明认证环节通过,仍需观察镜像层是否开始下载并最终完成。

实际拉取验证

docker pull hello-world:latest
docker pull namespace/image:tag
docker image inspect namespace/image:tag

只设置终端 HTTPS_PROXY,为什么 Docker pull 仍然超时?

因为发起外网请求的通常是 Docker daemon,而不是执行 docker 命令的 Shell。Shell 代理变量可能只影响当前终端启动的程序,不能保证系统服务、Docker Desktop 虚拟机或远程 Docker 主机继承设置。应在 daemon、Docker Desktop 或真正运行引擎的环境配置代理,然后通过拉取结果和 Clash 日志确认生效。

访问 Registry 返回 401,是不是代理配置失败?

不一定。未认证访问 Registry 的 /v2/ 接口可能返回 401 并要求获取令牌,这是服务端认证流程的一部分。如果 DNS、连接和 TLS 已建立,且响应来自 Registry,说明至少这次请求到达了目标;接下来应检查 Docker 登录、令牌请求是否通畅,以及实际镜像层下载是否成功。

Docker Hub 域名能解析,但镜像还是拉不下来,下一步查什么?

解析成功只证明某个环境获得了 DNS 答案,并不能证明 Docker daemon 通过了代理、认证和 layer 下载。先检查 Clash 日志中的实际目标域名、规则命中和出站节点,再确认 Docker daemon 的代理配置是否应用。若错误只出现在下载 layer 阶段,还要考虑 CDN 连接、节点带宽、出口稳定性和 Hub 限额。

Docker Desktop 能打开,是否代表它已经走 Clash?

不能。Docker Desktop 界面可用,只说明客户端进程可以运行;后台引擎的网络路径仍取决于 Desktop 代理设置、虚拟机网络和当前版本的实现。保存代理设置并按需重启后,用真实的 docker pull 验证,同时检查 Clash 是否记录了 Docker Hub 相关连接。

如果按上述顺序检查后仍无法稳定拉取,不要只凭浏览器速度判断节点质量:某些客户端的系统代理开关只覆盖桌面应用,Docker Desktop 或远程 daemon 仍可能使用另一条网络路径;手工维护规则也容易漏掉令牌与镜像层下载所需的主机。Clash V.CORE 可让你更直观地管理代理配置、检查分流并对照连接行为,适合把「请求是否进入代理」和「最终走哪个出站」逐项验证。需要更方便地完成配置与后续排障时,可以前往下载页选择适合当前系统的版本。

// 编辑推荐

让 Docker Hub 拉取路径清晰可查

使用 Clash V.CORE 管理代理与规则,并结合连接记录定位镜像拉取失败的环节。

  • 检查节点与策略组出站状态
  • 查看 Docker Hub 请求命中的规则
  • 对照代理模式与 DNS 解析结果
  • 减少终端与 Docker daemon 配置混淆
前往下载 →