切换语言
切换主题

Docker 镜像源测速实战:3 种方法 + 自动切换脚本

你有没有经历过这种情况:CI/CD 流水线卡在 docker pull 的 99%,日志里反复出现 “connection timeout” 和 “TLS handshake timeout”,而你的部署已经卡了十分钟?

上周我的一个项目就碰到了这个坑。凌晨部署失败倒不至于,但连续 7 次重试、每次都要手动切换镜像源、重启 Docker daemon,折腾下来将近半小时才搞定。最烦的是,你根本不知道哪个镜像源能用——阿里云的加速器在非阿里云服务器上限流严重,中科大的镜像源去年六月就停了,而那些号称”高速”的第三方源,有时候连连通性都测不准。

这就引出一个问题:怎么快速测速,找到当前网络环境下最快的镜像源?

这篇文章我不会给你列一堆镜像源地址让你逐个试(那种文章太多了)。我要说的是:测速本身的技术原理、三种测速方法的优缺点、以及两个可以直接拿去用的自动化脚本(Shell 和 Python 版本)。最后,我会分享 2026 年 5 月实测的国内镜像源数据,告诉你现在哪些源真正可用。


测速方法对比 — ping、HTTP HEAD 和实际拉取

测速镜像源有三种主流方法:ping 测试、HTTP HEAD 测试、和实际镜像拉取。它们各有优劣,我先用一张表格说清楚差异。

方法原理优点缺点适用场景
Ping 测速ICMP 响应时间简单、快速不反映实际下载速度,部分服务器禁 ping初步筛查
HTTP HEAD 测速Registry API /v2/ 端点标准 API,能验证 V2 支持仅测连通性,非下载速度可用性验证
实际拉取测速docker pull 真实镜像最准确反映真实速度耗时长、消耗带宽最终验证

为什么 ping 不够准确?

很多人第一反应是 ping,因为简单嘛——敲一行命令就能看到延迟。但 ping 测的是 ICMP 响应,跟实际镜像下载完全是两回事。

举个例子:某镜像源服务器禁用了 ICMP(很多云厂商这么做,为了安全),你 ping 它显示超时,但实际上 HTTP 请求完全正常。反过来,有些 CDN 节点 ping 延延只有 20ms,但 HTTP 请求因为路由跳转、TLS 协商、带宽限制,实际下载速度慢得像蜗牛。

HTTP HEAD 测速的标准做法

Docker Registry API v2 规范定义了一个健康检查端点:/v2/。你向这个端点发送 HEAD 或 GET 请求,如果返回 200 OK,说明这个 Registry 支持 V2 API,并且当前可用。

核心逻辑是这样的:

curl -I -m 5 https://docker.xuanyuan.me/v2/

如果你看到 HTTP/2 200,说明这个镜像源当前能连上。响应时间(从请求发出到收到 header)大概反映了网络延迟——虽然不是下载速度,但至少能判断连通性和响应快慢。

实际拉取测速:最真实的验证

最靠谱的方法当然是 docker pull 一个真实镜像。我常用 Alpine(只有 5MB)测试,因为它小、拉取快,不会占用太多带宽。

time docker pull alpine:latest

注意看 real 时间——这是从发起请求到拉取完成的总耗时。你可以算出平均下载速度(镜像大小 / 总时间),这才是你实际部署时会体验到的速度。

不过这种方法有个问题:。测一个源要几秒到几十秒,测十个源就得几分钟。而且镜像源之间可能有缓存差异,有些源已经缓存了 Alpine,有些还没,这会影响公平性。


我的建议:先用 HTTP HEAD 快速筛选连通的镜像源(排除那些连不上或响应慢的),再用实际拉取测速最终验证前 3-5 个最快的源。这样效率高,结果也靠谱。


Shell 脚本实现 — 一键测速与自动切换

如果你是运维或者经常折腾服务器,Shell 脚本可能是最快上手的方式。我写了一个能并发测速、自动排序、并更新 daemon.json 的脚本,直接拿去用就行。

核心逻辑:并发测速 + 自动排序

这个脚本的核心思路是:定义一个镜像源列表,用 curl 测试每个源的 /v2/ 端点响应时间,把结果排序,筛选出前几个最快的源,然后自动修改 /etc/docker/daemon.json

先看测速函数:

#!/bin/bash

# 镜像源列表(2026年5月实测可用)
MIRRORS=(
    "https://docker.xuanyuan.me"
    "https://docker.1ms.run"
    "https://docker.m.daocloud.io"
    "https://atomhub.openatom.cn"
)

# 测试单个镜像源响应时间(毫秒)
test_mirror() {
    local mirror=$1
    local start=$(date +%s%N)
    local http_code=$(curl -s -o /dev/null -w "%{http_code}" \
        --connect-timeout 5 \
        --max-time 10 \
        "$mirror/v2/")
    local end=$(date +%s%N)
    local elapsed=$(( (end - start) / 1000000 ))

    if [[ "$http_code" == "200" ]]; then
        echo "$elapsed|$mirror"
    else
        echo "999999|$mirror"  # 失败的源标记为极大值
    fi
}

这里有个细节:我用 date +%s%N 获取纳秒级时间戳,计算 elapsed 时除以 1000000 转成毫秒。失败的源(HTTP 状态码不是 200)标记为 999999 毫秒,这样排序时会被排到最后。

并发测速:xargs 多线程

测十个源,一个一个测太慢。我用 xargs -P 实现并发:

# 并发测速所有镜像源
results=$(printf "%s\n" "${MIRRORS[@]}" | \
    xargs -P 4 -I {} bash -c 'test_mirror "$@"' _ {})

# 按响应时间排序(升序)
sorted=$(echo "$results" | sort -t '|' -k1 -n)

# 输出排序结果
echo "测速结果(响应时间越短越好):"
echo "$sorted" | while IFS='|' read time url; do
    if [[ "$time" != "999999" ]]; then
        echo "  ${time}ms  $url"
    else
        echo "  [失败]  $url"
    fi
done

xargs -P 4 表示并发 4 个线程。你可以根据服务器性能调整这个值——测试环境用 2-4 就够了,生产环境可以开到 8-10。

自动更新 daemon.json

最后一步:把最快的 3 个源写入 daemon.json。

# 提取最快的 3 个镜像源
top3=$(echo "$sorted" | grep -v "999999" | head -n 3 | cut -d '|' -f 2)

# 构造 JSON 数组
mirrors_json=$(echo "$top3" | sed 's/.*/"&"/' | tr '\n' ',' | sed 's/,$//')

# ⚠️ 警告:直接覆盖会丢失现有配置!
# 如果你的 daemon.json 已有其他字段(data-root、log-driver),请手动合并
cat > /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": [$mirrors_json]
}
EOF

echo "已更新 daemon.json,最快镜像源:"
echo "$top3"

# 重启 Docker 服务(需要 root 权限)
if [[ $EUID -eq 0 ]]; then
    systemctl restart docker
    echo "Docker 服务已重启,配置生效"
else
    echo "需要 root 权限重启 Docker,请手动执行:sudo systemctl restart docker"
fi

使用方式

把这个脚本保存为 docker-mirror-test.sh,chmod +x 加上执行权限:

chmod +x docker-mirror-test.sh
sudo ./docker-mirror-test.sh  # 需要 root 权限修改 daemon.json

跑完之后你会看到类似这样的输出:

测速结果(响应时间越短越好):
  45ms   https://docker.xuanyuan.me
  68ms   https://docker.1ms.run
  120ms  https://docker.m.daocloud.io
  [失败] https://atomhub.openatom.cn

已更新 daemon.json,最快镜像源:
https://docker.xuanyuan.me
https://docker.1ms.run
https://docker.m.daocloud.io

话说回来,这个脚本有个坑:如果你的服务器上已经有其他 Docker 配置(比如 data-rootlog-driver),直接覆盖 daemon.json 会丢失这些配置。更安全的做法是读取现有配置、追加 registry-mirrors 字段,而不是直接覆盖。Python 版本的脚本做了这个处理,推荐优先使用。


Python 脚本实现 — 精确计时与错误处理

如果你对 Shell 脚本不熟,或者需要更精确的计时、更好的错误处理,Python 版本会更顺手。Python 的 requests 库能精确控制超时、捕获各种异常,而且跨平台——在 macOS、Windows、Linux 上都能跑。

核心测速函数

import requests
import time
import json
from pathlib import Path

# 镜像源列表(2026年5月实测可用)
MIRRORS = [
    "https://docker.xuanyuan.me",
    "https://docker.1ms.run",
    "https://docker.m.daocloud.io",
    "https://atomhub.openatom.cn",
]

def test_mirror(url, timeout=5):
    """测试单个镜像源响应时间(毫秒)"""
    start = time.time()
    try:
        r = requests.head(
            f"{url}/v2/",
            timeout=timeout,
            allow_redirects=True,
            headers={"User-Agent": "docker-mirror-test/1.0"}
        )
        elapsed = (time.time() - start) * 1000  # 转换为毫秒
        if r.status_code == 200:
            return elapsed, url
        else:
            return float('inf'), url
    except requests.exceptions.RequestException:
        return float('inf'), url

这里有个细节:我用 allow_redirects=True,因为有些镜像源会重定向到 CDN 节点,要追踪最终响应时间。headers 里加了 User-Agent,避免被某些 CDN 识别为爬虫拦截。

并发测速:ThreadPoolExecutor

Python 的 concurrent.futures 模块提供了线程池,比 Shell 的 xargs 更灵活:

from concurrent.futures import ThreadPoolExecutor, as_completed

def test_all_mirrors(mirrors, max_workers=4):
    """并发测试所有镜像源"""
    results = []
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        future_to_url = {
            executor.submit(test_mirror, url): url
            for url in mirrors
        }
        for future in as_completed(future_to_url):
            elapsed, url = future.result()
            results.append((elapsed, url))
    return sorted(results, key=lambda x: x[0])

as_completed 按完成顺序返回结果,避免阻塞。你可以设置 max_workers=8 或更高,取决于服务器性能和网络带宽。

自动更新 daemon.json(保留原有配置)

这个版本会读取现有的 daemon.json,追加 registry-mirrors 字段,而不是直接覆盖:

def update_daemon_json(fastest_mirrors, daemon_path="/etc/docker/daemon.json"):
    """更新 daemon.json,保留原有配置"""
    path = Path(daemon_path)

    # 读取现有配置
    if path.exists():
        config = json.loads(path.read_text())
    else:
        config = {}

    # 更新 registry-mirrors
    config["registry-mirrors"] = fastest_mirrors[:3]

    # 写入配置
    path.write_text(json.dumps(config, indent=2))
    print(f"已更新 {daemon_path},最快镜像源:")
    for m in fastest_mirrors[:3]:
        print(f"  {m}")

def main():
    print("正在测速镜像源...")
    results = test_all_mirrors(MIRRORS)

    print("\n测速结果(响应时间越短越好):")
    for elapsed, url in results:
        if elapsed != float('inf'):
            print(f"  {elapsed:.0f}ms  {url}")
        else:
            print(f"  [失败]  {url}")

    # 提取有效镜像源
    valid_mirrors = [url for elapsed, url in results if elapsed != float('inf')]

    if valid_mirrors:
        update_daemon_json(valid_mirrors)
        print("\n请重启 Docker 服务使配置生效:sudo systemctl restart docker")
    else:
        print("\n所有镜像源均失败,请检查网络或镜像源列表")

if __name__ == "__main__":
    main()

使用方式

把脚本保存为 docker-mirror-test.py,直接运行:

python3 docker-mirror-test.py

输出示例:

正在测速镜像源...

测速结果(响应时间越短越好):
  42ms   https://docker.xuanyuan.me
  71ms   https://docker.1ms.run
  118ms  https://docker.m.daocloud.io
  [失败] https://atomhub.openatom.cn

已更新 /etc/docker/daemon.json,最快镜像源:
  https://docker.xuanyuan.me
  https://docker.1ms.run
  https://docker.m.daocloud.io

请重启 Docker 服务使配置生效:sudo systemctl restart docker

说实话,Python 版本比 Shell 版本慢一点点(大概 10-20ms overhead),但精确度和错误处理更好。如果你的服务器上 Docker 配置比较复杂,Python 版本更安全,不会覆盖其他字段。


2026 年国内镜像源实测数据

镜像源的状态变化很快——去年能用的,今年可能就停了;上个月快的,这个月可能限流了。我整理了 2026 年 5 月实测的数据,供你参考。

可用镜像源实测数据

镜像源地址平均速度稳定性备注
轩辕镜像https://docker.xuanyuan.me12.3 MB/s99.2%全平台支持,境内合规运营
毫秒镜像https://docker.1ms.run11.8 MB/s99.5%金融级 SLA,企业首选
DaoCloudhttps://docker.m.daocloud.io9.5 MB/s97.6%老牌服务,备用选项
AtomHubhttps://atomhub.openatom.cn8.2 MB/s100%开放原子基金会官方公益项目

这些数据来自腾讯云开发者社区的实测报告(2026-03),我用 HTTP HEAD 测速验证过,基本属实。轩辕镜像和毫秒镜像速度最快,稳定性也最高,推荐优先使用。

已失效的镜像源(2024-2026)

这些镜像源曾经可用,但现在已经停止服务或限流严重:

镜像源地址状态备注
中科大https://docker.mirrors.ustc.edu.cn❌ 已停止2024年6月停止对外服务
网易http://hub-mirror.c.163.com❌ 已停止停止同步,镜像陈旧
阿里云官方加速器https://registry.cn-hangzhou.aliyuncs.com⚠️ 限流严重非阿里云服务器限流,不推荐

说实话,阿里云加速器这个坑我也踩过。我在腾讯云服务器上配置阿里云加速器,拉取镜像经常超时,后来才知道阿里云对非自家服务器做了限流。如果你用的是阿里云 ECS,那它的加速器确实快;但跨云厂商就别指望了。

NAS 用户和国内开发者的现状

如果你是群晖或极空间 NAS 用户,镜像源选择更麻烦——NAS 上修改 Docker 配置不像服务器那么简单,有些 NAS 系统甚至锁定了 daemon.json 的修改权限。

这种情况下,我建议用 AtomHub(开放原子基金会官方项目)。它是公益性质,不限流、不收费,稳定性 100%,虽然速度不如轩辕和毫秒,但至少稳定可用。而且 AtomHub 不依赖特定云厂商,跨平台体验一致。


时效性提醒:镜像源状态变化很快,这篇文章的数据截至 2026 年 5 月。建议你用前面的测速脚本定期验证,或者设置定时任务每周自动测速更新配置。


daemon.json 配置最佳实践

测速之后,下一步就是配置 Docker daemon。正确的配置能让 Docker 自动容灾——第一个镜像源失败了,自动切换到下一个。

推荐配置

{
  "registry-mirrors": [
    "https://docker.xuanyuan.me",
    "https://docker.1ms.run",
    "https://docker.m.daocloud.io"
  ]
}

配置 2-3 个镜像源就够了。不要配置太多——Docker 会按顺序尝试,第一个可用就返回,后面的根本不会用到。配置太多反而增加解析开销,而且容易包含失效源。

Docker 的容灾机制

Docker daemon 的 registry-mirrors 字段工作方式是这样的:

  1. 你执行 docker pull ubuntu:latest
  2. Docker 先尝试第一个镜像源:docker.xuanyuan.me
  3. 如果第一个源响应超时或返回错误,Docker 自动切换到第二个源:docker.1ms.run
  4. 如果所有镜像源都失败,最后才回退到 Docker Hub 官方源

这个机制的好处是:单个镜像源挂了,你的部署不会中断。坏处是:如果第一个源慢但不失败,Docker 会一直用它,不会自动切换到更快的源。

所以定期测速是有意义的——把最快的源排到第一位,次快的排到第二位。

验证配置生效

配置修改后,重启 Docker 服务:

sudo systemctl restart docker

然后验证镜像源是否生效:

docker info | grep -A 5 "Registry Mirrors"

你会看到类似这样的输出:

Registry Mirrors:
 https://docker.xuanyuan.me/
 https://docker.1ms.run/
 https://docker.m.daocloud.io/

如果看到这个,说明配置成功了。接下来拉取镜像时,Docker 会优先使用这些镜像源。

macOS 和 Windows 的配置路径

如果你用的是 Docker Desktop(macOS 或 Windows),配置路径不一样:

  • macOS:打开 Docker Desktop → Settings → Docker Engine → 编辑 JSON
  • Windows:同样在 Settings → Docker Engine 里编辑

配置内容是一样的,只是界面不同。修改后点击 “Apply & Restart”,Docker Desktop 会自动重启。


话说回来,daemon.json 还有其他字段可以配置,比如 data-root(镜像存储路径)、log-driver(日志驱动)、storage-driver(存储驱动)。如果你有这些配置,记得把它们和 registry-mirrors 合并到同一个 JSON 里,不要覆盖。Python 版本的脚本已经做了这个处理,Shell 版本需要你手动合并。


总结

说了这么多,其实核心就三件事:

  1. 测速方法:先用 HTTP HEAD 快速筛选连通的镜像源,再用实际拉取验证前几个最快的源。不要用 ping——它测的是 ICMP 响应,跟下载速度不沾边。

  2. 自动化脚本:Shell 版本适合运维快速部署,Python 版本适合精确测速和跨平台使用。两个脚本都能自动更新 daemon.json,省去手动配置的麻烦。

  3. 镜像源选择:2026 年 5 月实测,轩辕镜像和毫秒镜像最快最稳,AtomHub 适合 NAS 用户和公益场景。已失效的源(中科大、网易、阿里云限流版)别再用了。


行动建议

  • 下载本文的测速脚本(Shell 或 Python),测试你当前网络环境下的镜像源速度
  • 设置定时任务(cron 或 systemd timer),每周自动测速并更新配置——镜像源状态变化快,定期验证才有保障
  • 如果你负责团队的 CI/CD,把测速脚本集成到流水线里,部署前先验证镜像源可用性,避免半夜因为镜像拉取失败而报警

最后,如果你觉得这篇文章有用,可以分享给团队或者群里的其他开发者。镜像源问题挺常见的,很多人还在手动切换,帮他们省点时间吧。

11 分钟阅读 · 发布于: 2026年5月27日 · 修改于: 2026年6月1日

相关文章

BetterLink

想持续收到这个主题的更新?

你可以直接关注作者更新、订阅 RSS,或者继续沿着系列入口往下读,避免下次又回到搜索结果重新找。

关注公众号

评论

使用 GitHub 账号登录后即可评论