public-image-mirror 内网镜像缓存实战:基于 Registry 3 构建本地 Pull-Through Cache
【免费下载链接】public-image-mirror很多镜像都在国外。比如 gcr 。国内下载很慢,需要加速。致力于提供连接全世界的稳定可靠安全的容器镜像服务。项目地址: https://gitcode.com/GitHub_Trending/pu/public-image-mirror
本篇基于 docs/local-cache/README.md 展开,讲解如何在内网环境部署一套本地镜像缓存:借助 Docker Registry 3 的 proxy 模式对接 public-image-mirror(即m.daocloud.io),把常用镜像缓存到内网,降低对外网依赖。读完本文,你可以独立完成从 Docker Compose 编排、Registry 配置、Docker 客户端适配到拉取验证的全链路操作,并理解 proxy、TTL、存储目录等参数背后的工作机制。
为什么需要在内网部署镜像缓存
在公网直接使用m.daocloud.io加速镜像拉取时,每次拉取最终仍要经过一次"内网 → 公网加速节点 → 源 Registry"的链路。而内网环境(如 VPC 内部集群、生产机房、离线程度较高的机房)通常存在两类问题:
- 外网带宽不稳定或成本敏感:大量节点重复拉取相同镜像时,流量会反复穿透公网;
- 可用性要求高:对外网服务的依赖越多,构建/部署链路越脆弱。
本地缓存部署的定位正是:在内网中架设一个镜像仓库,把常用镜像缓存下来。首次拉取仍会回源(回源到m.daocloud.io,由它再去同步上游源站),但之后的拉取直接命中内网缓存,从而减少对外网的依赖。
这套做法与 README.md 中"最佳实践"章节的"部署内网缓存"一节一脉相承——它是官方推荐的把加速能力引入内网的方案,本文即是该方案的完整实操展开。
工作原理:Registry 3 的 proxy 模式
内网缓存的核心是一个运行pull-through cache(拉取式缓存)模式的 Docker Distribution Registry。与普通仓库不同,proxy 模式的 Registry 自身不要求你手动docker push:当客户端向它拉取某个镜像而本地没有时,Registry 会按配置到远端 URL 回源拉取,并把结果落盘到本地存储;后续相同请求则直接命中本地。
这一点可以直接从本文档给出的 Registry 配置中确认(见下一节完整docker-compose.yml):
proxy: remoteurl: https://m.daocloud.io ttl: 2160hremoteurl指定回源地址。这里回源到m.daocloud.io,意味着内网缓存实际是"两级缓存"的第二级:m.daocloud.io是第一级(它缓存上游docker.io、gcr.io等源站),你的内网 Registry 是第二级;ttl为缓存条目的存活时间,本文档取值2160h(90 天),超过 TTL 的缓存条目会被视为过期、重新回源。
上游第一级缓存的行为在 README.md 中有明确说明,可以作为理解整条链路的背景:
- 所有 hash(sha256)与源保持一致(懒加载机制);
m.daocloud.io缓存的内容只保留 30 天,过期后需要重新同步;- Manifest 内存缓存 1 小时,tag 更新后约 1 小时才会同步新的;
- Blob 内存缓存 1 分钟,期间若 blob 到达 30 天期限被删除,可能报 404。
也就是说,内网缓存命中时完全走内网流量;未命中时请求会依次经过 内网 Registry →m.daocloud.io→ 源站,此时延迟主要由公网回源决定。理解这个链路后,"为什么内网第二次拉取飞快"就很好解释了。
部署步骤
1. 准备环境
确保目标机器已安装Docker和Docker Compose(docker compose子命令形式,Docker 20.10+ 内置的 Compose v2 均可)。
2. 配置 Docker Compose 文件
创建一个docker-compose.yml,内容如下(完整继承自 docs/local-cache/README.md):
services: registry: image: m.daocloud.io/docker.io/library/registry:3 restart: unless-stopped ports: - 8888:8888 command: - /etc/docker/registry/config.yml volumes: - cache-data:/var/lib/registry configs: - source: registry-config target: /etc/docker/registry/config.yml configs: registry-config: content: | version: 0.1 storage: delete: enabled: true filesystem: rootdirectory: /var/lib/registry http: addr: :8888 proxy: remoteurl: https://m.daocloud.io ttl: 2160h volumes: cache-data: {}逐项说明各配置的作用:
| 配置项 | 作用 |
|---|---|
image: m.daocloud.io/docker.io/library/registry:3 | 缓存 Registry 自身的镜像也走加速源拉取,避免"用镜像加速服务的镜像来部署它自己"时的鸡生蛋问题 |
ports: 8888:8888 | 把容器内 Registry 监听端口 8888 映射到宿主机 8888;如内网习惯其他端口,只需改映射的左侧并同步更新客户端配置 |
command: /etc/docker/registry/config.yml | 指定 Registry 启动时使用的配置文件路径(镜像默认即该路径,这里显式写出便于理解) |
volumes: cache-data:/var/lib/registry | 将缓存数据目录挂载到命名卷,Registry 落盘的 manifest/blob 都保存在这里;用命名卷而非绑定目录,可随容器生命周期管理 |
restart: unless-stopped | 异常退出自动拉起,保证缓存服务持续可用 |
configs: registry-config | 通过 Compose configs 机制把 Registry 配置以匿名文件形式注入容器,避免再维护一个独立配置文件 |
内嵌的 Registry 配置(configs部分)要点:
storage.filesystem.rootdirectory: /var/lib/registry:缓存数据的根目录,与上方卷挂载点一一对应;storage.delete.enabled: true:开启删除能力。配合 pull-through 场景,Registry 在清理过期(超过ttl)缓存条目时可以真正删除存储内容,避免缓存卷无限膨胀;http.addr: :8888:监听容器内所有网卡的 8888 端口,是客户端访问的入口;proxy.remoteurl: https://m.daocloud.io:回源地址;proxy.ttl: 2160h:缓存存活 90 天,过期后重新回源。
3. 启动服务
docker compose up -d启动后可用docker compose ps与docker compose logs registry确认服务正常,并确认宿主机 8888 端口已监听。
4. 配置 Docker 客户端
由于内网缓存 Registry 走的是明文 HTTP(内网场景下没有额外部署 TLS 证书),Docker 客户端需要把它声明为可信的不安全 Registry。编辑/etc/docker/daemon.json,添加:
{ "insecure-registries": ["<your-registry-ip>:<your-registry-port>"] }将<your-registry-ip>、<your-registry-port>替换为缓存 Registry 实际的内网 IP 与端口(按上文示例即宿主机 IP 与8888)。然后重启 Docker 服务使配置生效:
systemctl restart docker说明:如果你的内网环境部署了统一 CA 签发的证书,也可以走 HTTPS 并去掉
insecure-registries;但 docs/local-cache/README.md 给出的标准方案就是明文 +insecure-registries,在内网中是常见且简单的做法。
用法:像使用 m.daocloud.io 一样加前缀
部署完成后,<your-registry-ip>:<your-registry-port>/就成为m.daocloud.io/的本地缓存代理。使用规则与直接使用m.daocloud.io完全一致:在原镜像地址前加前缀即可,只是前缀从m.daocloud.io换成了你的内网地址。
例如,拉取docker.io/library/nginx:latest镜像:
docker pull <your-registry-ip>:<your-registry-port>/docker.io/library/nginx:latest该请求的处理过程:
- 客户端向
http://<your-registry-ip>:<your-registry-port>发起 pull; - 内网 Registry 查本地存储,命中则直接返回(纯内网流量);
- 未命中则回源
https://m.daocloud.io,由它再按自身缓存/回源逻辑取到镜像,同时写入内网本地缓存,供后续节点复用。
这套前缀规则与 README.md 中"增加前缀"的推荐方式一致,内网 Registry 只是把第一级前缀"本地化"了。
与直接使用 m.daocloud.io 的差异
| 维度 | 直接使用 m.daocloud.io | 部署内网缓存后 |
|---|---|---|
| 前缀 | m.daocloud.io/... | <your-registry-ip>:<your-registry-port>/... |
| 命中缓存时的网络路径 | 节点 → 公网加速节点 | 节点 → 内网 Registry |
| 回源链路 | 加速节点 → 源站(懒加载) | 内网 Registry →m.daocloud.io→ 源站 |
| 对外网依赖 | 每次拉取都依赖外网可达 | 仅首次/过期回源时依赖外网 |
| 适用场景 | 单点、节点少的公网环境 | 内网集群、机房批量拉取 |
另外结合上游缓存特性(见 README.md):m.daocloud.io侧缓存只保留 30 天、Manifest 内存缓存 1 小时,因此即使内网侧设置了 90 天 TTL,长期不拉的镜像在 30 天后回源也可能需要重新同步——这是"懒加载 + 两级缓存"的正常表现,属于适用前提与限制。
运维与排障要点
结合上文配置,给出几条与实现直接对应的检查项:
- 缓存数据落盘位置:
docker volume inspect <项目名>_cache-data可查看命名卷实际路径;镜像内容全部位于/var/lib/registry下。内网盘容量要能容纳目标镜像的累计大小,ttl: 2160h决定了过期条目才会被清理,容量规划需按"常用镜像全集"估算; - 端口不通时:确认
docker compose ps中容器在运行、宿主机 8888 监听正常、内网安全组/防火墙放行了 8888;客户端daemon.json中声明的 IP:端口必须与ports映射的宿主机端口一致; - 拉取报 404:若上游源站/加速侧的 blob 恰好处于过期清理窗口,可能出现瞬时 404(对应 README.md 中"Blob 内存缓存 1 分钟,期间如果 blob 到达 30 天期限被删除,导致会报 404"的说明),重试即可;
- 只读使用:本方案中内网 Registry 只承担 pull 角色,无需为它配置推送认证;不要把内网缓存 Registry 当作品号仓库使用;
- 镜像白名单背景:回源的
m.daocloud.io服务于有白名单约束的镜像集合,本仓库以 allows.txt 维护允许的镜像前缀(含*、**等通配规则),其格式可由 hack/verify-allows.sh 中的匹配逻辑印证——逐行判断前缀是否以**(任意深度子路径)、*(仅一级路径)或精确镜像名结尾,再与请求镜像做前缀比对。因此内网缓存能拉到的范围天然等于m.daocloud.io允许的范围,部署本地缓存不会扩大这个范围,只会改变流量路径。
小结
- 内网缓存 = 一个 proxy 模式的 Registry 3,
proxy.remoteurl指向m.daocloud.io,ttl: 2160h控制缓存过期; - 完整部署仅需一份内嵌
configs的docker-compose.yml(端口 8888、卷cache-data、回源地址、TTL 四处关键参数); - 客户端在
daemon.json中声明insecure-registries后重启 Docker; - 使用方式与
m.daocloud.io完全同构:把前缀m.daocloud.io/换成<your-registry-ip>:<your-registry-port>/即可; - 命中走内网、未命中回源两级缓存,容量规划与 404 排查均可从 TTL 与缓存生命周期解释。
【免费下载链接】public-image-mirror很多镜像都在国外。比如 gcr 。国内下载很慢,需要加速。致力于提供连接全世界的稳定可靠安全的容器镜像服务。项目地址: https://gitcode.com/GitHub_Trending/pu/public-image-mirror
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考