1. 为什么 Docker 镜像下载总让人头疼
先说实话,玩 Docker 这么久,最烦的不是镜像构建失败、不是容器起不来,而是那个白底蓝字的鲸鱼图标卡在 Pulling 界面,一行Downloading后面跟着[=============>]走了十分钟还不到一半。这种经历,用过 Docker 的人基本都碰到过。
问题的根源在于 Docker Hub 这个官方仓库离我们太远。镜像文件动不动几百 MB,跨洋传输本来就慢,再加上 Docker Hub 的分发节点在高峰时段极其不稳定,拉个nginx:alpine这种几十 MB 的小镜像都可能超时中断。这时候就需要给 Docker 配置一个"国内镜像源加速列表",让拉取请求走国内节点,速度能快上好几个量级。简单说,就是你从国外书店买书慢,那就让国内书店先进口一批存货放本地,你直接从本地拿。
这篇文章不打算讲那些已经被反复写过、但实际已经失效的老教程。今天正好是 9 月 13 日,我把目前实测过、社区反馈仍然可用的镜像源整理了一份,顺便把配置方法、验证方式、常见报错一并写清楚。不管你是刚装好 Docker Desktop 的新手,还是正在被拉取超时折磨的老手,这篇都能帮你省下不少时间。
2. 镜像源的工作原理和核心概念
2.1 registry mirror 到底是什么
在动手配置之前,先把这个概念捋清楚。Docker 的镜像加速,本质上是通过 Docker 引擎自带的registry-mirrors配置项,把镜像拉取请求转发到一个镜像源站点。这个站点扮演的角色是"缓存代理",它会在你请求时去 Docker Hub 拉取一份镜像,然后缓存到自己的服务器上,下一次再有人拉同一个镜像,就直接从缓存里返回。
这里要特别注意一个误区:registry mirror 只对 Docker Hub 官方镜像(也就是镜像名前不带其他仓库地址的,比如nginx、mysql、redis)生效。如果你拉取的是ghcr.io/xxx或quay.io/xxx这种第三方仓库的镜像,配置这个镜像源是没用的,因为请求根本不会走这条链路。想加速第三方仓库镜像,你得用"替换镜像地址前缀"的方式,把ghcr.io/xxx手动改成镜像站地址/ghcr.io/xxx,这属于另一种玩法,后面会单独提。
2.2 为什么镜像源频繁失效
很多人困惑,上个月还能用的镜像源,今天怎么突然拉不了镜像了。这里面有运营成本的问题,也有合规性的问题。一个公共镜像源,存储和带宽都是真实开销,用的人越多成本越高,一旦运营方扛不住就不再提供服务了。还有一些源因为管理不善被滥用来做违法的事情,导致整个域名被限制访问。这就是为什么网上那些两年前的文章里推荐的源,现在基本全军覆没。
所以我的建议是:不要只信一份列表"用到底",要养成定期验证的习惯。我自己是每一个季度左右检查一次手头的镜像源列表,把失效的剔除,补上新的。这也正是这篇文章存在的意义——给你一份经过实测的基准清单,同时教会你验证方法。
2.3 镜像站和加速器怎么选
市面上的方案大概分三类:
第一类是公共镜像站,直接配置到registry-mirrors即可使用,优点是零门槛,缺点是稳定性全看运营方心情。
第二类是云厂商提供的加速器,一般也只对腾讯云、阿里云等自家用户开放,属于"没有注册就没有服务"的范畴,而且现在多数已经不对外开放了。
第三类是自建方案,拿一台国内服务器部署一个镜像缓存服务,或使用 Cloudflare Workers 这类边缘函数做请求转发。优点是稳定可控,缺点是需要一定的动手能力。
对绝大多数用户来说,第一类公共镜像站就够用了,折腾自建反而没必要。这篇文章主要讲的也是这一类。
3. 2026 年 9 月实测可用的镜像源清单
3.1 九月的可用列表
先说清楚,下面这份清单是我在 9 月 7 日到 9 月 13 日之间逐一拉取hello-world和nginx:alpine实测过的。测试环境包括一台 Ubuntu 服务器、一台 CentOS 服务器和一台 Windows Docker Desktop,三次都成功的我才放进来。镜像源变动快,你看到这篇文章的时候也许有部分已经失效,这很正常,按后面第 5 章的验证方法重新过一遍就好。
| 镜像源地址 | 状态 | 备注 |
|---|---|---|
https://docker.1ms.run | ✅ 可用 | 速度稳定,体积较大的镜像表现不错 |
https://docker.1panel.live | ✅ 可用 | 1Panel 官方维护的源,近期恢复 |
https://docker.m.daocloud.io | ✅ 可用 | DaoCloud 的老牌源,存活时间较长 |
https://dockerproxy.net | ✅ 可用 | 社区共建,速度中等 |
https://hub.rat.dev | ✅ 可用 | 社区者维护,偶尔需要切换协议 |
https://docker.1panelproxy.com | ✅ 可用 | 1Panel 备用域名,可作为替补 |
https://dockerhub.icu | ⚠️ 不稳定 | 时好时坏,可作为最后备选 |
这个小节的结论是:不要只配一个源,建议把前三个都配上。Docker 引擎在拉取镜像时会按顺序尝试多个 mirror,第一个失败自动回退到第二个,多配几个能显著提高成功率。
3.2 为什么列表里的源换了一批
如果你翻过两年前的帖子,会发现当时主流的源和现在完全不同,比如早年的docker.mirrors.ustc.edu.cn已经停服很久了,阿里云/腾讯云的加速器地址也在不断收紧。普通用户不需要深究具体原因,只需要记住一个规律:镜像源名单就是一份不断滚动更新的名单,没有谁可以保证永久可用。
另外提醒一句,有一些来路不明的源,你可能在 QQ 群或论坛里看到有人推荐。使用前务必多留个心眼,镜像源理论上能拿到你拉取的所有镜像内容,如果它本身被恶意篡改过,你拉下来的镜像很可能带着后门。尽量选择有品牌背书的(比如上表中的 1Panel、DaoCloud),或者社区口碑好的。
4. 镜像源配置实操:从 Linux 到 Windows 全覆盖
4.1 守护进程配置法(Linux 通用)
Linux 下配置 Docker 镜像源的核心是修改/etc/docker/daemon.json文件。先检查这个文件是否存在:
sudo cat /etc/docker/daemon.json如果文件不存在或者内容是空的,直接新建一个,写入下面这段:
{ "registry-mirrors": [ "https://docker.1ms.run", "https://docker.1panel.live", "https://docker.m.daocloud.io" ] }如果文件里已经有其他配置项,比如"data-root"或"log-driver",千万不要直接覆盖,手动把registry-mirrors这个键合并进去即可,改完之后大概是这个样子:
{ "data-root": "/var/lib/docker", "registry-mirrors": [ "https://docker.1ms.run", "https://docker.1panel.live", "https://docker.m.daocloud.io" ] }保存退出后,分两步重启 Docker:
sudo systemctl daemon-reload sudo systemctl restart docker注意:很多教程只写restart docker不写daemon-reload,这样偶尔会出现配置不重载的情况。先重新加载 systemd 管理配置,再重启服务,这套连招最稳。
4.2 Docker Desktop 配置法(Windows / macOS)
Windows 和 macOS 上装的是 Docker Desktop,配置方式比 Linux 简单,不用碰命令行改文件。
先打开 Docker Desktop,点击右上角的小齿轮进入 Settings,然后找到 Docker Engine 选项卡,你会看到一个 JSON 编辑框。把registry-mirrors加进去,同样将三个地址都填上:
{ "registry-mirrors": [ "https://docker.1ms.run", "https://docker.1panel.live", "https://docker.m.daocloud.io" ] }点击右下角的 Apply & Restart,Docker Desktop 会自动重启并加载新配置。
顺带说一个坑:Windows 上如果 Docker Desktop 一直启动失败,提示 "virtualization support not detected" 或者连不上 docker api,那就不是镜像源的问题了。先检查 BIOS 里虚拟化是不是被关了,再看 Windows 功能里 Hyper-V 和 WSL2 有没有启用。镜像源配置得再好,Docker 引擎起不来都是白搭。
4.3 containerd 和 Podman 怎么配
有读者可能在用 containerd 或 Podman 作为容器运行时,这两种工具的配置位置和方法完全不同,我单独列出来。
containerd 的配置文件默认在/etc/containerd/config.toml。如果你用的是 containerd 1.x,配置镜像源的方式是在[plugins."io.containerd.grpc.v1.cri".registry]和configs这两个区块里做设置:
[plugins."io.containerd.grpc.v1.cri".registry] [plugins."io.containerd.grpc.v1.cri".registry.mirrors] [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"] endpoint = ["https://docker.1ms.run", "https://docker.1panel.live"]改完以后重启 containerd:
sudo systemctl restart containerdPodman 的配置则放在/etc/containers/registries.conf,追加下面这段内容:
[[registry]] location = "docker.io" [[registry.mirror]] location = "docker.1ms.run" [[registry.mirror]] location = "docker.1panel.live"Podman 和 Docker 的命令行高度兼容,配置完直接podman pull nginx就能走加速。
4.4 验证配置是否生效的两种方法
配置完成以后,第一件事是验证。最简单的方法是用docker info查看 Registry Mirrors 字段:
docker info | grep -A 3 "Registry Mirrors"如果输出里有你填写的那几个地址,说明配置已经加载。但要注意,配置加载了不等于拉取就一定快,所以第二步是实测拉取:
docker pull hello-world docker pull nginx:alpinehello-world体积极小,主要用来验证链路通不通;nginx:alpine稍微大一点,能测出真实速度。两个都拉完没有超时,说明加速生效了。顺手再执行一次docker system df,看看镜像有没有正确落盘。
5. 拉取镜像的常见报错排查
5.1 报错速查表
实际使用中会遇到各种报错,我把频率最高的几个整理成一张表,方便直接对照:
| 报错关键字 | 原因 | 解决办法 |
|---|---|---|
dial tcp: lookup registry-1.docker.io: no such host | 本地 DNS 解析异常 | 换 DNS 为223.5.5.5/114.114.114.114后重启 Docker |
net/http: request canceled (Client.Timeout exceeded) | 默认仓库连接超时 | 确认镜像源已正确配置,且源地址能正常访问 |
x509: certificate signed by unknown authority | 镜像源证书问题 | 换个镜像源,或检查系统时间是否准确 |
manifest unknown | 镜像标签不存在 | 检查镜像名和 tag 是否拼写正确,nginx不等于nginx:latest |
pull access denied | 镜像不存在或为私有仓库 | 确认仓库名称,登录 Docker Hub 后再拉取私有镜像 |
failed to get console mode for stdout: The handle is invalid | Windows 上运行交互命令时的兼容问题 | 在 PowerShell 中执行,不要用 CMD 旧窗口 |
5.2 配置已经生效但还是拉不动
这种情况很常见,docker info里明明能看到镜像源地址,拉取nginx:alpine就是超时。我遇到过几次,基本都是下面两种原因:
一是镜像源站点本身已经挂了,但因为是配置了多个 mirror,Docker 在尝试第一个源超时之后不会立刻切换,而是要一直等到本轮超时结束才尝试第二个,所以体感就是"卡死"。解决办法是调整daemon.json里的顺序,把当前最快的源放到第一位,或者直接去掉失效的源。
二是镜像源只支持 HTTPS 且证书链不完整,某些老版本 Docker 会校验失败。可以先用 curl 测试源地址的通达性:
curl -I https://docker.1ms.run/v2/如果返回 HTTP 401 或 200,说明源是通的,问题出在 Docker 配置;如果返回 502 或者超时,说明这个源已经不可用,换一个即可。
5.3 换了新源但老源还在生效
有一种迷惑性很强的情况:你改了daemon.json,重启之后docker info显示的还是旧配置。大概率是改错了文件。比如 Linux 上 Docker 有全局配置和用户级配置之分,某些发行版的 Docker 会额外读取/etc/docker/daemon.json,路径错一个字都不行。
建议用以下命令确认当前 Docker 实际读取的配置路径:
docker info --format '{{.DockerRootDir}}'然后检查/etc/docker/daemon.json中是否混入了多余逗号或注释。JSON 严格来讲不支持注释,你手写的时候加//注释会直接导致解析失败,Docker 静默忽略整个文件,继续用默认配置。这是我踩过最蠢的坑,没有之一。
6. 进阶技巧:为第三方仓库镜像加速
6.1 registry mirror 的边界
前面说了,registry-mirrors只加速 Docker Hub 官方镜像。如果你在拉取ghcr.io/automatic/xxx或quay.io/prometheus/node-exporter这类镜像时遇到速度瓶颈,配置官方仓库的 mirror 是没有任何作用的。
这类镜像的加速思路是"地址替换":把镜像名前缀替换成镜像站地址。比如你想拉ghcr.io/owner/app:latest,而镜像站支持对 ghcr.io 的代理,你就可以直接写:
docker pull docker.1ms.run/ghcr.io/owner/app:latest拉取成功后,再用docker tag改回原始镜像名:
docker tag docker.1ms.run/ghcr.io/owner/app:latest ghcr.io/owner/app:latest这样组织镜像名和标签,后续使用docker-compose.yml时不至于因为镜像名不一致而报错。注意,不是所有镜像源都支持代理第三方仓库,使用前先看镜像站首页的说明,或者直接拉一个第三方仓库镜像试错。
6.2 脚本批量替换镜像地址
如果你在部署一个包含十几个服务的项目,手动改镜像名太痛苦了。写个简单的 Shell 脚本就能批量替换:
#!/bin/bash IMAGES=( "ghcr.io/owner/app:latest" "ghcr.io/owner/web:latest" "quay.io/prometheus/node-exporter:latest" ) for img in "${IMAGES[@]}"; do new_img="docker.1ms.run/${img}" echo "Pulling ${new_img}" docker pull "${new_img}" docker tag "${new_img}" "${img}" done注意:docker-compose.yml里如果写了镜像名,运行时你要保证本地有这个镜像名的镜像。所以docker tag这一步不是可选项,是必须做的。
6.3 自建私有缓存库的构想
如果是团队内部使用,镜像源频繁失效的折腾时间累积起来非常可观。更稳妥的方案是部署一个私有的 Docker Registry 缓存,让团队成员统一走内网镜像源,外部源失效只影响缓存刷新,不影响已有镜像的拉取。
具体方案是使用registry:2镜像,配合proxy.remoteurl环境变量指向https://registry-1.docker.io,再给本机配置 Nginx 反向代理和缓存目录。这类部署需要有一定的 Docker Compose 基础,篇幅所限不展开写,但方向值得有长期需求的小伙伴参考。
7. 其他用户常踩的性能和权限问题
7.1 macOS / Windows 下容器与宿主机时间不同步
这个问题在 macOS 上比较典型。如果你拉取的镜像构建后运行日志时间不对,甚至出现证书校验失败,先检查容器内时间:
docker exec -it <container_id> date如果容器内时间比宿主机晚 8 小时,大概率是 WSL2 或 macOS 虚拟时钟的问题。Windows 下可以执行wsl --shutdown后重启 Docker Desktop;macOS 下重启 Docker Desktop 一般也能恢复。这个问题和镜像源没有直接关系,但排查问题时容易被误判成镜像源故障。
7.2 Docker 权限错误
Linux 下新装 Docker 后,直接执行docker ps可能会报:
permission denied while trying to connect to the Docker daemon socket这是因为当前用户不在docker用户组里。执行下面两条命令:
sudo usermod -aG docker $USER newgrp docker之后重新打开终端,权限就正常了。注意:加入 docker 组的用户和 root 实际拥有同等级权限,给普通用户加组要谨慎。
7.3 关于青龙面板、ruoyi 这类项目的镜像拉取
不少同学用 Docker 跑青龙面板或 RuoYi 这类业务项目时,经常在拉取基础镜像阶段就卡住。这类项目的docker-compose.yml里写死的是 Docker Hub 官方镜像名,配置好 registry mirror 之后直接docker compose up -d就能自动走加速,不需要修改 yml 文件。如果拉的是带有复杂 tag 的版本(比如2.22.0-ubuntu),建议先确认镜像站是否缓存过这个冷门 tag,没有的话第一次拉取仍然会较慢,但至少不会被超时中断。
7.4 磁盘空间不足的隐患
镜像源加速只是解决拉取速度,解决不了磁盘空间。如果 Docker 根目录所在分区快满了,拉大镜像时也会报错,表现形式类似超时。用docker system df查看空间占用,用docker system prune -a清理无用镜像。这个命令会把所有没在运行的容器使用的镜像都删掉,执行前确认没有需要保留的本地镜像。
8. 我的一点心得体会
写到这儿,镜像源这件事基本说透了。最后分享一个我自己的使用习惯:我从来不会只依赖一个镜像源,而是固定维护一个"主用 + 备用 + 兜底"的三层结构。主用源选速度最快的,备用源选品牌背书的,兜底源选社区活跃的,每个季度花两分钟验证一轮,有失效的直接从列表里删掉补新的。
还有一个细节,如果你用的是国内云服务器,在拉取镜像前可以先看一眼内网是否已经提供了对应的镜像服务,比如云厂商容器镜像服务(ACR / CCR)都支持配置专属加速地址,走内网甚至公网速度都比公共镜像源更稳定。当然,这类服务多数需要注册和实名认证,但对企业用户来说是更值得投入的方案。
镜像源这份列表注定是一份"保质期有限"的文档,但我希望这篇文章给的验证方法和配置思路能长期帮到你。毕竟工具会变,解决问题的思路不会。