1. 先说结论:2026年9月7日,这份镜像源实测清单长这样
每年换一次配置总比临时抱佛脚强。今年我把手上的Docker环境全部重新刷了一遍镜像源,包括Windows上的Docker Desktop、两台Ubuntu服务器,以及一台CentOS的老机器。折腾半天,最直接的感受是:镜像源列表不是越长越好,真正能稳定返回镜像层的,就那么几个。
先说这次实测的结论,省得你往下翻半天。
| 镜像源 | 地址 | 是否需要账号 | 实测状态 | 备注 |
|---|---|---|---|---|
| 阿里云容器镜像加速器 | https://xxxx.mirror.aliyuncs.com | 需要 | 可用 | 每个账号一个专属地址,需在控制台获取 |
| DaoCloud公共镜像源 | https://docker.m.daocloud.io | 不需要 | 可用 | 公共地址,我这边测试速度不错 |
| 腾讯云加速器 | https://mirror.ccs.tencentyun.com | 不需要 | 可用 | 适合腾讯云内网环境,外网也能用 |
| 中科大镜像源 | https://docker.mirrors.ustc.edu.cn | 不需要 | 可用 | 老牌源,部分时段需要多试几次 |
| 清华镜像源 | https://mirrors.tuna.tsinghua.edu.cn/docker-ce/ | 不需要 | 仅软件源 | 注意,这个只用于Docker安装包,不是registry-mirror |
| 网易镜像源 | https://hub-mirror.c.163.com | 不需要 | 已失效/不稳定 | 我这边多次超时,不建议作为第一优先级 |
| 南京大学镜像源 | https://docker.nju.edu.cn | 不需要 | 可用 | 但偶尔返回校验错误,建议放后面 |
我把这些源按照“可用性优先级”排了个序,实际写入配置文件时,顺序很重要。Docker在拉取镜像时会从左往右依次尝试,如果第一个源返回404或者网络超时,它未必会自动切换到第二个,这取决于具体错误类型。所以我的建议是:把最靠谱的放第一个,失效概率高的放最后甚至直接不写。
顺带说一句,网上有些文章会把各种大学和云厂商的源一股脑堆成七八个,实际效果反而变差。因为部分公共源限速或者对Docker Hub某些镜像做了白名单限制,多个慢源叠加只会让拉取时间更长。我这次测试后最终只留下三个:阿里云、DaoCloud、中科大。
为什么需要额外准备一份镜像源列表?核心原因还是“拉不动”。Docker Hub上的镜像虽然能直接访问,但跨网络拉取吞吐量经常在几十KB/s徘徊,碰到大镜像(比如PyTorch、GitLab、MySQL)基本等于浪费时间。而国内可用的registry mirror本质上是Docker Hub的只读缓存,把镜像层缓存到离你更近的节点,拉取速度提升一个量级。
我这次专门验证了不同源的拉取速度。拉一个约300MB的mysql:8.0镜像,阿里云加速器大概用了一分半,DaoCloud用了两分钟,中科大用了三分多。速度波动受本地带宽和时段影响很大,但至少都比直连强得多。
2. 配置镜像源的完整动作:Docker Desktop、Linux服务器一个不落
配置镜像源,核心操作就是改daemon.json。但Docker Desktop和Linux整个逻辑不完全一样,容易踩坑的地方也不一样。
2.1 在Docker Desktop上配置
Windows和Mac上的Docker Desktop提供了图形化入口,但本质上还是写daemon.json。打开Docker Desktop,进入Settings -> Docker Engine,你会看到一段JSON配置。这是Docker Desktop合成的配置,不要直接复制网上别人的完整内容,只需要把registry-mirrors这一段加进去。
我的配置如下:
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://docker.mirrors.ustc.edu.cn" ] }如果你有阿里云专属加速地址,可以放在第一位:
{ "registry-mirrors": [ "https://你的ID.mirror.aliyuncs.com", "https://docker.m.daocloud.io" ] }填完先点Apply & restart,让Docker Desktop带着新配置重启。重启后打开终端执行:
docker info看输出里的Registry Mirrors字段,如果列出了你刚才填的地址,说明配置生效。这一步很多人忽略,其实是最快的验证方式。
2.2 Linux服务器上不要漏掉复杂环境
Linux服务器上的Docker一般通过systemd管理,配置文件路径通常是/etc/docker/daemon.json。如果文件不存在,直接新建一个。注意一个很容易错的点:这个文件是JSON格式,不是JSONC,所以不能有注释,逗号必须放在正确位置。我之前见过不少人在文件里写// 注释然后导致dockerd起不来的情况。
推荐配置:
{ "registry-mirrors": [ "https://你的ID.mirror.aliyuncs.com", "https://docker.m.daocloud.io", "https://docker.mirrors.ustc.edu.cn" ] }改完之后不能直接重启docker,还得先让systemd重新加载配置:
sudo systemctl daemon-reload sudo systemctl restart docker然后同样用docker info验证。这里多提醒一句:如果你用的是Rootless Docker,配置路径会变成~/.config/docker/daemon.json,别改错地方。
另外有同学会遇到“改了daemon.json但docker info没有显示Registry Mirrors”的情况,通常是Docker版本太旧,或者配置文件里写了"registry-mirrors"但键拼错了。建议先执行docker version确认版本,低于20.10的可以直接升级。
2.3 一个容易被忽略的细节:Docker Hub仓库名的解析规则
配置了镜像源之后,拉取镜像的地址还是docker pull nginx或者docker pull mysql:8.0,不需要改成镜像源地址后加仓库名那种写法。原因在于registry mirror是一个透明代理,Docker会继续使用docker.io/library/前缀,只是从镜源拉取。有些同学理解成“需要把镜像源作为镜像名的一部分”,这是不对的。
但有个特例:公共镜像源不一定缓存了所有Docker Hub仓库,尤其是一些冷门镜像或很新的tag,第一次拉取时镜像源会回源到Docker Hub,这时速度依然可能不快。这时候你只能等它回源完成,或者直接用Docker Hub直连拉一次。
3. 镜像源拉不下来时的排查链路:从报错到恢复的完整过程
镜像源配置好不代表万事大吉。我在这次测活过程中就遇到了三类问题,每一个都值得单独拿出来说说。
3.1 镜像源失效的典型报错与快速确认方法
最常见的报错长这样:
Error response from daemon: Get "https://docker.mirrors.ustc.edu.cn/v2/": net/http: TLS handshake timeout或者:
Error response from daemon: Get "https://hub-mirror.c.163.com/v2/": dial tcp: lookup hub-mirror.c.163.com: no such host前者说明网络能到对方,但连接超时,可能是源限流或网络环境问题。后者说明DNS解析失败,大概率是某个源已经停止服务或做了访问限制。
遇到这种报错,先别急着改配置。我一般用一条命令测试该源当前是否可访问:
curl -I https://docker.mirrors.ustc.edu.cn/v2/正常会返回HTTP/2 200或者401。注意看,返回401其实也说明服务是通的,只是Docker Hub那边要求认证;如果返回503、502或者直接超时,这个源基本可以放弃。
我这次测试时,网易源hub-mirror.c.163.com就已经稳定超时了,所以果断把它从配置里删掉。
3.2 Docker Desktop无法识别虚拟化(virtualization support not detected)的修复过程
这个热搜词很典型:virtualization support wasn't detected。很多人在安装完Docker Desktop,双击启动后弹出类似提示,说虚拟化支持未检测到。这个问题和镜像源无关,但如果你修不好,后面配置镜像源全白搭。
排查分三步:
第一步,确认Windows虚拟化是否开启。打开任务管理器 -> 性能 -> CPU,看右下角“虚拟化”一栏,如果显示“已启用”,说明BIOS层面没问题;如果显示“已禁用”,需要重启进入BIOS,把Intel Virtualization Technology或AMD-V打开。
第二步,确认Windows可选功能打开。以管理员身份运行PowerShell:
dism.exe /online /enable-feature /featurename:Microsoft-Hyper-V-All /all /norestart然后重启电脑。注意,如果你的机器没有Hyper-V支持,这条命令可能报错。建议先确认CPU型号。除了Hyper-V,还需要确认“Windows Hypervisor Platform”这个功能是否开启。可以Dashboard里搜索“启用或关闭Windows功能”,把这两项都勾上。
第三步,Docker Desktop设置里选择正确的后端。新版Docker Desktop默认使用WSL2,如果你更习惯用Hyper-V,可以在Settings -> General里调整“Use the WSL 2 based engine”的开关,但必须保证对应功能已启用。
我之前在处理这个问题时,遇到过BIOS里开启了虚拟化,但Windows功能里Hyper-V和虚拟机平台没开,结果Docker Desktop依然报同样的错。后来把两项功能都打开并重启,问题才解决。
3.3 多个镜像源并存时的fallback机制没有想象中那么智能
Docker的registry-mirrors支持配置多个地址,但它的fallback机制并不完美。实测下来,如果第一个源对某个镜像没有缓存,它会去上游拉取并缓存,这个过程可能很慢;而如果第一个源返回404或403,Docker才会尝试第二个源。很多超时错误并不会触发fallback,而是直接卡住直到超时。
这也是为什么我一直强调“列表宁缺毋滥”。如果你第一个源已经不可用,配置再多也没用,反而浪费时间。我现在的做法是:定期(大概三个月一次)跑一遍测活脚本,把失效源从列表里踢掉,把新出现的好源提到前面。
4. 镜像源之外,还有两个让你少等半天的细节
镜像源列表只是“拉得快”的一半,另一半藏在日常操作习惯里。这类问题不会让你拉不下来,但会严重影响效率。
4.1 Dockerfile下载依赖时,别让镜像内流量成了新瓶颈
很多场景是这样的:你配置好了registry-mirror,基础镜像拉取很快,但进入Dockerfile构建阶段,apt-get install、pip install、npm install这些步骤依然慢得离谱。原因很简单:构建阶段容器内部访问的系统源、包管理源并不会自动走镜像源。
我拿Python项目举例,在Dockerfile里可以这样设置pip镜像源:
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple RUN pip install -r requirements.txt或者直接一行搞定:
RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt对于apt系系统,部署时会替换为国内debian源。基础镜像如果是Ubuntu,可以在Dockerfile里加:
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list这样构建速度能提升一大截,至少不要白白浪费时间。
4.2 docker pull卡在“等待”状态时,先检查磁盘和存储驱动
镜像源配置没问题,速度也正常,但拉取一个大镜像时经常卡在Downloading很久不动。这一般不是网络问题,而是Docker存储驱动和磁盘空间在扯后腿。
先用docker system df看一下镜像、容器、缓存占了多少空间。如果空间不足,docker会在解压镜像层时无限等待。清理命令:
docker system prune -af注意-a会删除所有未被容器使用的镜像,别在生产环境随便跑。存储驱动方面,推荐使用overlay2。查看方式:
docker info | grep "Storage Driver"如果显示的是aufs或vfs,建议升级到新版本Docker。尤其在有大量小文件的基础镜像上,overlay2的解压效率明显更高。
4.3 拉取到本地后要善用tag固化,减少重复拉取
镜像源加速再快,也不如本地不拉。同一个镜像如果只是tag不同,比如mysql:8.0和mysql:8.0.29,镜像层大部分一样,Docker会自动复用已有层。但如果你每次都用latest,当镜像更新时就得重新拉差异层,慢又占空间。建议部署时固定明确版本号,然后在本地保留副本,下次部署直接docker load,不需要每次都去镜像源。
5. 用MySQL 8.0和Redis主从验证镜像源配置到底有没有生效
光看docker info显示配置项还不够,我习惯用真实场景跑一遍,确认实际拉取过程真的走了镜像源。
5.1 基于加速源安装MySQL 8.0并初始化
配置完mirror后,我拉取MySQL 8.0:
docker pull mysql:8.0如果镜像源生效,拉取速度应该明显比你直连时快。拉完后直接启动:
docker run --name mysql8 \ -e MYSQL_ROOT_PASSWORD=yourpassword \ -p 3306:3306 \ -d mysql:8.0启动容器后,等待几秒,执行:
docker exec -it mysql8 mysql -uroot -pyourpassword这里有个小坑:新版MySQL 8.0镜像启动时会自动初始化数据目录,如果第一次启动失败,需要先看日志:
docker logs mysql8常见问题是MYSQL_ROOT_PASSWORD强度不够,或者端口冲突。与镜像源无关,不要瞎猜网络问题。
5.2 基于加速源搭建Redis主从
Redis主从是热搜词之一,我也顺便验证了一下。用一个docker-compose.yml启动一主一从:
services: redis-master: image: redis:7.0 container_name: redis-master command: ["redis-server", "--requirepass", "masterpass"] ports: - "6379:6379" redis-slave: image: redis:7.0 container_name: redis-slave command: ["redis-server", "--slaveof", "redis-master", "6379", "--masterauth", "masterpass"] depends_on: - redis-master启动:
docker compose up -dRedis 7.0镜像大约几十MB,拉取耗时很短。如果镜像源失效,这里会明显卡住。主从起来后,验证同步是否正常:
docker exec redis-slave redis-cli -a masterpass info replication观察master_link_status:up就说明主从连接成功。这里我踩过一个坑:--slaveof参数在Redis 5.0之后仍然可用,但如果主节点设置了requirepass,从节点必须配masterauth,否则主从日志里会一直刷MASTER abo错误。
5.3 验证镜像源命中率:如何知道请求真的走了镜像源
想确认实际拉取走了哪个镜像源,有个简单办法:拉取一个镜像时,同时打开Docker Desktop的日志,或者用docker events观察。更直观的是直接查看镜像源的访问日志,但公共源一般不开放。
还有一个办法是看镜像表里的下载时间。拉取一个你确信没缓存过的镜像,比如冷门tag,如果瞬间完成,说明这个源已经有了缓存;如果卡很久,说明源在回源。这个很难有精确数字,但体感上很有参考价值。
实际操作中,我习惯在拉取大镜像时用time docker pull测一下总耗时。不同时段、不同镜像结果波动很大,但只要能在五分钟内拉完一个三百兆的镜像,基本说明配置已经生效。我这次用mysql:8.0测试,整体耗时约一分半,对比失效前动辄十几分钟的体验,已经算理想状态。
镜像源清单这种东西,更新频率其实很快。今天是2026年9月7日,我手里这份列表是我实测过、能用的版本;再过几个月,说不定又有变化。所以我最后想分享的小技巧是:别把任何一份列表当成永久的,定期跑一遍curl测活,比收藏一堆文章有用得多。