前一阵把主力开发机迁移到新系统,Docker 装好后第一件事就是拉mysql:8.0。结果老收藏夹里那几个“国内镜像源地址”接连败下阵来——不是 TLS handshake timeout,就是直接 403。去论坛翻了十几个“最新可用 Docker 国内镜像源”的帖子,一大半还是好几年前复制粘贴的老清单,照着配完照样拉不动。
于是这轮赶在 9 月 11 日更新前,我把市面上能叫得上名的 Docker 国内镜像源逐个拉了一遍,整理出这份 2026 年实测仍可用的加速列表,同时把 Linux、Windows、macOS 三种环境下的配置办法、验证命令,以及常见的 pull 失败排查链路一并写清楚。如果你是刚装好 Docker 想快速跑起来 mysql / redis / gitlab,或者被 Docker Desktop 启动问题折腾得头大,这篇应该正好用得着。
1. 2026年9月实测仍可用的镜像加速源清单
1.1 先泼盆冷水:那些“老牌源”为什么一个个倒下
在列可用清单之前,我建议你先调整一个预期:镜像加速源不是一个“申请一次就能用十年”的东西。很多老教程里反复出现的几个地址,现在要么连接超时,要么返回 403/404。原因无非这么几种:
- 服务商停止该公共项目,域名进入维护状态;
- 原地址迁移到新域名,旧地址保留但不再更新;
- 源站增加了鉴权策略,匿名请求被拒绝;
- 外部依赖环境调整,公共缓存服务被限制或下线。
所以判断一个镜像源还能不能用,最有效的办法不是看帖子发布日期,而是自己动手探测 + 实测拉取。这也是我坚持把“验证方法”放在清单前面的原因。
1.2 用一条命令先给候选源“体检”
在没有配 Docker 之前,你可以先对候选镜像源执行连通性探测。Docker registry 的 v2 接口会返回一个固定响应头,只要 URL 能通就代表服务基本在线:
curl -I https://docker.m.daocloud.io/v2/正常响应会带HTTP/1.1 401 Unauthorized或HTTP/2 401。看到 401 别慌,registry 要求请求带 token 属于正常机制,关键是连接没有被拒绝,也不是 TLS 握手超时。
再用time观察 DNS 解析和连接耗时:
time curl -I https://docker.m.daocloud.io/v2/如果real时间动辄超过 5 秒,说明该源当前网络链路不乐观,基本不具备拉大镜像的能力。
1.3 2026年9月实测可用的地址汇总
下面这份表格是我这轮逐个验证过的。分为“公共源”和“个人专属源”,后者要先登录服务商控制台获取专属地址,但稳定性通常更好:
| 镜像源 | 性质 | 2026-09 实测状态 | 使用建议 |
|---|---|---|---|
https://docker.m.daocloud.io | DaoCloud 公共源 | 可拉取,速度中上 | 不想注册账号时的首选公共源 |
https://mirror.ccs.tencentyun.com | 腾讯云公共源 | 可拉取,速度稳定 | 服务器在腾讯云内网时延迟极低 |
https://docker.mirrors.tencent.com | 腾讯云公共源备用地址 | 可拉取 | 适用于非腾讯云环境的备选 |
https://<你的ID>.mirror.aliyuncs.com | 阿里云个人专属源 | 可拉取,速度快 | 需要登录容器镜像服务控制台获取专属地址 |
https://docker.mirrors.ustc.edu.cn | 中科大源 | 状态不稳定 | 不建议作为唯一源,可放末尾兜底 |
提示:公共源地址随时可能调整,使用前最好先按上面 curl 命令自测。表格状态只能代表 2026 年 9 月中旬我这个网络环境的结论,不同地区、不同运营商访问同一源,体验差异可能很大。
个人专属地址的获取方式很简单:登录阿里云控制台,找到“容器镜像服务”下的“镜像加速器”页面,页面会直接给出形如https://一串ID.mirror.aliyuncs.com的地址,复制出来填进 daemon.json 即可。
2. 镜像加速源的内在逻辑:从一条 docker pull 命令说起
2.1 docker pull 究竟干了什么
很多人配置镜像源只是照着抄,出了问题就不知道怎么排查。想搞清楚,得先看docker pull ubuntu:latest到底做了几步:
- Docker Engine 解析
ubuntu:latest对应的 manifest; - manifest 中包含镜像每一层 layer 的 digest;
- Engine 按 digest 逐个下载 layer 数据;
- 全部下载完成后做校验、解压、合并,生成本地镜像。
配置registry-mirrors后,Engine 会优先向 mirror 请求这些数据。mirror 里如果没有对应 layer,就由 mirror 服务端返回或 Engine 回源 Docker Hub 拉取。不过要注意:不同版本 Docker 对 mirror 缺失内容的处理行为并不完全一致,有些版本会回源拉,有些版本会直接报错manifest unknown。这也是为什么你明明配了镜像源,有时还是会在日志里看到它去请求 Docker Hub 的原因之一。
用一个生活化的类比:镜像加速源像是你家楼下的快递代收点。平时包裹先送到代收点,你再走几步去取;代收点没有某个包裹,快递员要么改派到别处,要么直接告诉你这个件签收不了。关键是,代收点有的包裹,最终内容和官方站点送来的应当完全一致——Docker 每一层都有 digest 校验,哪怕从加速源拉取,也绕不过这层完整性验证。
2.2 多个镜像源的优先级和失败切换
registry-mirrors在 daemon.json 里是一个数组,Docker Engine 会按照数组顺序依次尝试。第一优先级不可用,就会自动尝试下一个。这个设计让“配两个源”变得很有必要:一个源挂了,另一个还能兜底。
但多源也不是灵丹妙药。两个镜像源缓存的内容并不完全一致,某一层在 A 源有缓存在 B 源可能没有;如果 A 源已经进入半死状态(TCP 能连接但传输极慢),Engine 不会聪明地立刻切换到 B,而是会在超时之后再试。实际感受就是“明明配了三个源,pull 还是卡很久”。
所以我个人建议:主力源放一个,备用源放一个到两个,最多不超过三个。堆太多没有意义,反而会让第一个超时拖垮整体体验。
2.3 镜像加速器的边界:管不到 ghcr / gcr / quay
这是一个高频误区:很多人以为配了 Docker 国内源,所有仓库都变快。其实registry-mirrors只对 Docker Hub 的镜像生效,ghcr.io、gcr.io、quay.io、registry.k8s.io这些外部 Registry 的镜像拉取并不走这个配置。
如果你的项目要从这些仓库拉镜像,通常做法是:
- 提前把所需镜像通过
docker pull拉到本地,再用docker save导出 tar,部署时docker load导入; - 或者使用支持跨地域同步的容器镜像仓库服务,把海外仓库的镜像同步到国内仓库后,再修改 tag 拉取。
这块就不是 registry mirror 能压平的问题了。这也能解释为什么很多教程教你在 daemon.json 里加了镜像源后,拉某个特定镜像还是超时——先确认你要拉的那个镜像到底在哪个 Registry,别把锅全扣在镜像源头上。
3. Linux、Docker Desktop 三种环境下的镜像源配置实操
3.1 Linux 上通过 daemon.json 配置
Linux 下配置镜像源是最直接的,因为 Docker daemon 的配置入口就是/etc/docker/daemon.json。完整步骤如下:
- 确认 Docker 在运行:
docker version; - 创建或编辑
/etc/docker/daemon.json; - 写入
registry-mirrors数组; - 重启 Docker:
systemctl daemon-reload && systemctl restart docker; - 验证配置:
docker info输出中的Registry Mirrors字段。
一份直接可用的示例配置:
{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://mirror.ccs.tencentyun.com", "https://docker.mirrors.tencent.com" ] }这里有几个非常关键的坑,都是我踩过的:
daemon.json必须是合法 JSON,末尾逗号、注释都不能有。之前见过同事在文件里加了// 注释,Docker 直接起不来。- 改完不重启不会生效,
docker info不会显示新源。 - 如果 Docker 服务起不来,先看日志:
journalctl -u docker -n 100,多半是 JSON 解析错误。
3.2 Windows / macOS 上 Docker Desktop 的配置差异
Docker Desktop 的图形界面提供了配置入口:Settings -> Docker Engine。这个界面本质上就是在编辑 Desktop 内置引擎的daemon.json,保存后 Desktop 会自动重启引擎。
但有一个非常典型的坑:如果你在 Windows 上通过 WSL2 里自己安装了 docker-ce(比如 Ubuntu 子系统里apt install docker.io),那么你改 Docker Desktop 的 Settings 并不会影响 WSL2 里的 docker daemon。WSL2 内的是独立进程,要改就改 WSL 内的/etc/docker/daemon.json。
判断自己在用哪个 Docker:
docker context ls docker version看看 Client 和 Server 的路径是否指向同一个环境。很多时候拉不到镜像不是源配置错了,而是你改的 daemon 和实际用的 daemon 不是同一个。
另外,相关搜索里经常出现Docker Desktop failed to start because virtualisation support wasn't detected这种报错。这个报错跟镜像源毫无关系,根因是 Windows 虚拟化支持没开:BIOS 里的 VT-x/AMD-V、Windows 功能里的“虚拟机平台”和 WSL2 都要开启。如果卡在这条,优先检查:
systeminfo | findstr "Hyper-V"输出里有“已检测到虚拟机监控程序”或类似提示才算正常。这个检查顺序也建议刻进肌肉记忆:先确认 Docker Desktop 启动正常,再谈镜像源配置。
3.3 docker-compose 场景需要额外配置吗
不需要。Compose 只是把多个容器的启动参数声明成 YAML,拉镜像的操作最终仍然交给 docker daemon 执行,daemon 的registry-mirrors配置会被自动复用。
也就是说,你只要把 daemon 配好,docker compose up -d时拉取mysql:8.0、redis:7.2这些镜像自然走加速。不要再单独去给 Compose 找什么“镜像源配置”,那是没有的东西。
4. docker pull 失败的排查链路:从超时到 403
4.1 先分清问题类型
镜像源配置完成后,拉镜像依然可能失败。别急着换源,先看报错。我把常见现象整理成一张表,你可以按图索骥:
| 报错现象 | 大概率原因 |
|---|---|
tls: handshake timeout | 网络链路到镜像源不通,或源已停止服务 |
403 Forbidden/denied | 源要求鉴权,或匿名拉取被拒绝 |
manifest unknown | 镜像名/tag 错误,或镜像源没有缓存该内容且不会回源 |
dial tcp i/o timeout | 本机到镜像源超时,多为防火墙/安全组拦截 |
repository does not exist | 镜像名拼写错误,或该镜像确实在远端不存在 |
卡在Waiting不报错 | 网络二层问题,TCP 连接建立后传输极慢 |
4.2 完整的五步排查链路
第一步:确认 daemon 配置生效。
docker info 2>&1 | grep -A 5 "Registry Mirrors"如果输出为空,说明配置根本没加载,直接回到第 3 节的步骤重新检查 JSON 和重启操作。
第二步:测试镜像源连通性。
curl -I https://docker.m.daocloud.io/v2/连接超时就是网络层问题,401 反而说明服务在线。
第三步:检查 DNS 解析耗时。
time getent hosts docker.m.daocloud.io如果解析耗时超过 1 秒,考虑换 DNS 服务商或者直接改用 IP 直连的源。
第四步:开启 Docker daemon 调试日志,观察实际访问的域名和 IP。
修改/etc/docker/daemon.json加一行:
{ "debug": true, "registry-mirrors": [ "https://docker.m.daocloud.io" ] }然后重启 Docker,用journalctl -u docker -f观察。如果引擎启动后长时间没有请求日志,说明问题出在客户端或网络层。
第五步:用一个小镜像做对照测试。
docker pull hello-world docker pull alpine:3.19如果小镜像秒拉完,说明源本身没问题,换成大镜像卡住往往是网络带宽或源服务端限速,而不是配置故障。
4.3 一个真实的排查案例
有次朋友反馈docker pull mysql:8.0报 403,查下来发现他配置的 daemon.json 里第一个镜像源是个人专属地址,但地址里的 ID 是从网上抄来的别人的,当然 403。换成自己控制台里获取的专属地址后问题解决。
这说明一个很容易被忽略的点:个人专属地址和公共源的鉴权策略不同,不能混用。网上抄来的专属地址里带着别人的 ID,拉取时源站识别不了你的身份,自然拒绝请求。凡是看到mirror.aliyuncs.com前面跟着一串莫名 ID 的配置,都要警惕。
5. 镜像源只是起点:几个高频业务镜像的落地细节与相关误区
5.1 mysql:8.0 与 redis 主从:加速只解决第一步
镜像源配好后,最直观的收益是docker pull mysql:8.0从原来的十几分钟变成几十秒。但要注意,镜像拉下来只是起点。
举个例子,快速跑一个 MySQL 8.0:
docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORD=yourpassword \ -p 3306:3306 \ -v /data/mysql:/var/lib/mysql \ mysql:8.0镜像源解决的是“镜像能不能快速下载”的问题,容器启动后的端口映射、时区、数据持久化、字符集这些配置,该踩的坑一个都不会少。
再比如 Redis 主从,用 compose 声明最方便:
services: redis-master: image: redis:7.2 container_name: redis-master command: ["redis-server", "--appendonly", "yes"] ports: - "6379:6379" redis-slave: image: redis:7.2 container_name: redis-slave command: ["redis-server", "--slaveof", "redis-master", "6379"] depends_on: - redis-master这里镜像源帮忙把两个 redis:7.2 镜像快速拉下来,但主从是否连通、网络模式是否合适,还是要靠容器日志和实际读写去验证。
5.2 gitlab 这种“大块头”镜像:如何最大化利用加速
gitlab/gitlab-ce 镜像动辄几个 GB,用公共源和直连 Docker Hub 拉取的时间差距会非常明显。但有几个细节需要特别注意:
- 建议先
docker pull gitlab/gitlab-ce:latest确认镜像源没有问题,再跑容器;不要第一次就docker run让它在启动时现拉镜像,出问题不好区分是网络还是配置。 - GitLab 容器本身对内存要求较高,至少 4GB 以上,否则启动后各种 500。
external_url、SSH 端口映射、GITLAB_ROOT_PASSWORD这些核心配置,镜像源帮不上任何忙。
换句话说,镜像源加速解决的是“拿到镜像”这个环节,镜像起来之后的运维复杂度是另一回事。
5.3 别把“ollama 国内镜像源”和 Docker 镜像源混为一谈
相关搜索里“ollama 国内镜像源”热度一直很高,这里一定要说清楚:Ollama 本身不是通过 Docker Hub 分发模型下载,ollama pull llama3下载的模型文件来自模型托管服务。所以即便你的 Docker 镜像源配置满血,也不会让ollama pull变快。
如果你在 Docker 容器里跑 Ollama,镜像源加速只会影响ollama/ollama这个镜像本身的拉取,不涉及后续模型文件的下载。
同理,pip、npm、conda 的加速分别是 pip 镜像、npm 镜像和 conda 镜像,跟 Docker registry mirror 也不是一回事。清华、阿里、腾讯都有各自的镜像站,需要哪个就去配哪个,不要把几套完全不同的加速机制搅在一口锅里。
最后说点我个人这些年用下来的体会。镜像源列表这种东西,更新得越快、写得越长,越容易给人“齐全”的错觉,但实际上你只需要挑 1 个主力源 + 1 个备用源,然后固定一个检查节奏,每两个月 curl 一遍就够。我现在主力用的是 DaoCloud 公共源,腾讯云那个作为备用;服务器部署到腾讯云内网时才会换成mirror.ccs.tencentyun.com的内网地址。平时尽量不要往 daemon.json 里堆七八个第三方来源不明的源头,镜像缓存是会被供应链攻击盯上的地方,配置的源头越少、越可控,越安全。
如果你按这篇文章配置完,还是碰到拉取超时或启动异常,最管用的不是到处复制别人的 daemon.json,而是先跑一遍docker info和curl -I,确认配置真的加载、源真的可达。把这两个动作搞成肌肉记忆,大部分问题都能在一分钟内定位。