pnpm pnpr 的 OCI 容器镜像服务:用 docker / podman / skopeo 向 pnpr 推送镜像
pnpm pnpr 的 OCI 容器镜像服务用 docker / podman / skopeo 向 pnpr 推送镜像【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm导读本指南讲解 pnpm 项目新引入的 pnprpnpm 的 Rust 实现容器镜像服务能力只需在注册表配置中声明ecosystem: ocipnpr 就会以标准 OCI Distribution 协议对外提供镜像仓库可用docker、podman、skopeo直接推送与拉取。读完本文你将掌握如何在 pnpr 中声明 OCI 注册表、用docker login pnpr token 完成认证、理解/v2/API 与镜像命名规则并深入看到这一功能背后的 OCI 协议实现manifest、digest、镜像文档、referrers 等。功能总览pnpr 从包注册表到镜像仓库在 pnpm 仓库的变更说明 .changeset/serve-container-images.md 中pnpm/pnpr以minor版本引入了如下能力pnpr now serves container images. Declare a registry withecosystem: oci. Push to it withdocker,podman, orskopeo. The distribution API answers at/v2/on the host root. An image keeps its own name, with no registry key in the path. Sign in withdocker login, using a pnpr token as the password.翻译并展开这一变更意味着pnpr 不仅仅能代理 npm / cargo / pypi 等软件包生态还能直接充当容器镜像仓库注册表通过ecosystem: oci声明纳入 pnpr 统一的注册表路由与访问控制体系服务端实现的是标准OCI Distribution Specification因此 Docker 生态的任意客户端docker、podman、skopeo都能开箱即用认证复用 pnpr 自身的 token 体系用户不需要额外引入独立的镜像仓库服务。OCI 协议层的纯数据实现集中在 pnpr/crates/oci/src/lib.rs其模块注释明确写道这是pnpr 所讲的 OCI distribution 协议The OCI distribution protocol pnpr speaks包含三部分命名所有 blob 的Digest、客户端推送的Manifest形状以及托管注册表为每个仓库保存的ImageDocument。配置如何声明一个ecosystem: oci的注册表配置项解析在 pnpr/crates/config/src/config_file.rs 中hosted托管型注册表与upstream上游代理型注册表都带有一个ecosystem字段注释说明该字段决定此注册表服务的包生态进而选择它使用的协议。当取值是oci时pnpr 就以 OCI Distribution 协议对外服务。从 pnpr/crates/config/src/registry_graph.rs 的生态组ecosystem group展开逻辑看配置既可以采用组语法也可以采用单条声明语法组语法oci:组下的所有注册表自动继承ecosystem: oci并且org存储归属默认取oci~namedefaultRegistry等默认路由也会带上oci/前缀单条语法显式写ecosystem: oci。例如 pnpr/crates/config/src/tests/registry_graph.rs 中的测试就使用了ecosystem: oci的 hosted 注册表并验证resolve_default(Ecosystem::Oci, repository)的路由行为pnpr/crates/config/src/tests/storage.rs 则验证了生态组的名称作用域、默认注册表与存储组织规则。一个最小可用的声明大致如下以测试中出现的生态组语法为基础# pnpr 配置文件config.yaml registries: oci: images: # 注册表名存储 org 默认成为 oci~images type: hosted ecosystem: oci # 组内可省略此处显式写出更清晰说明具体的access/packages权限规则沿用 pnpr 统一的注册表访问控制模型ecosystem: oci的键名同样会经过生态相关的规范化校验见 pnpr/crates/config/src/registry_graph/namespace.rs。协议选择如何影响路由在 pnpr/crates/config/src/registry_graph.rs 中Npm之外的生态会被逐一登记进路由表oci作为独立生态获得自己的默认注册表与来源解析pnpr/crates/config/src/lib.rs 中还提供了独立的OciConfig位于http.oci下其中包含max_manifest_bytes、max_blob_bytes等大小限制供服务端在读取 manifest / blob 请求体时做上限校验。推送容器镜像docker / podman / skopeo配置好ecosystem: oci的注册表后即可用任意 OCI 兼容客户端推送镜像。以docker为例# 1. 登录密码使用 pnpr token见下文认证一节 docker login pnpr.example.com # 2. 给本地镜像打上 pnpr 仓库的 tag docker tag my-app:1.0.0 pnpr.example.com/my-app:1.0.0 # 3. 推送 docker push pnpr.example.com/my-app:1.0.0podman、skopeo用法等价podman push pnpr.example.com/my-app:1.0.0skopeo copy docker-daemon:my-app:1.0.0 docker://pnpr.example.com/my-app:1.0.0。推送过程本质上是分两步完成的这与 pnpr 的存储模型深度绑定见 pnpr/crates/oci/src/lib.rs 的模块注释上传 blob层与配置镜像的 config 与每一层 layer 都是内容寻址、不可变的字节块客户端先把它们上传到blobs/uploads/写入 manifest发布提交点上传完成后客户端PUT一份 manifest引用这些 blob 的 digest。只有 manifest 写入才算发布了一个版本——没有任何 manifest 引用的 blob 只是待回收的垃圾而不是发布了一半的版本。镜像清单的形态校验pnpr 在 pnpr/crates/oci/src/manifest.rs 定义了接受的 manifest 结构schemaVersion仅接受 2Docker schema 1 早已废弃而被拒绝、mediaType、config一个 Descriptor、layers、manifests用于镜像索引、subjectreferrer 机制、artifactType与annotations。校验规则manifest.rs包括schemaVersion必须是 2mediaType未声明时回退到请求头Content-Type再回退到默认的 OCI image manifest非索引类 manifest 必须携带configdescriptor带subject的 referrer 若本身不是索引则必须携带artifactType或可推导的 config mediaType。支持的媒体类型为了兼容大多数客户端仍然推送 Docker 旧类型的现实见 pnpr/crates/oci/src/media_type.rspnpr 同时接受 OCI 与 Docker 两类 manifest 媒体类型lib.rs媒体类型含义application/vnd.oci.image.manifest.v1jsonOCI 镜像 manifestapplication/vnd.oci.image.index.v1jsonOCI 镜像索引application/vnd.docker.distribution.manifest.v2jsonDocker 镜像 manifestapplication/vnd.docker.distribution.manifest.list.v2jsonDocker manifest 列表命名与路径/v2/与镜像自带名字Distribution API 挂载点OCI Distribution 协议要求所有端点位于镜像引用主机名下的/v2/路径。在 pnpr/crates/oci/src/lib.rs 中这个段被定义为常量/// The path segment every distribution endpoint sits under. pub const API_SEGMENT: str v2;客户端根据镜像引用的 host 推导出 API 地址因此该段不能移动或重命名。pnpr/crates/pnpr/src/server/oci/tests.rs 的测试验证了这一点例如api_base(/v2/acme/app/manifests/1.0, ...)解析出的 API 根就是/v2。镜像名中不含 registry key变更说明特别强调An image keeps its own name, with no registry key in the path. 也就是说镜像引用形如pnpr.example.com/acme/app:1.0.0路径中的仓库名是acme/app不会把注册表的 key如oci/images塞进镜像名。registry key 只影响 pnpr 内部的路由与存储归属org默认为oci~name不影响对外协议层的命名。服务端对/v2/name/type/reference的路由实现位于 pnpr/crates/pnpr/src/server/oci/manifest_request.rsHEAD/GET/PUT/DELETE四种方法的 manifests 端点与 pnpr/crates/pnpr/src/server/oci/discovery.rsGET /v2/_catalog仓库列表、GET /v2/name/tags/list标签列表。标签与引用规则pnpr/crates/oci/src/lib.rs 实现了 distribution 规范的 tag 语法[a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}最大长度MAX_TAG_LEN 128首字符必须是 ASCII 字母数字或下划线后续字符仅允许字母数字、.、_、-。manifest 引用只有两种形态tag 或 digest除此之外一律拒绝——既防止存下任何符合规范的客户端都无法寻址的元数据也避免sha256:short这类长得像 digest的 tag 混入标签列表。标签是仓库里唯一的可变对象pnpr/crates/oci/src/document.rs 对TagEntry的设计值得关注每个 tag 记录tag、指向的digest以及updatedUnix 毫秒时间戳。标签是仓库中唯一可变的东西因此已存在即优先的不可变合并规则不适用于 tag——崩溃恢复后重放旧事务会把 tag 拖回旧 manifest。改为按时间戳比较后合并是单调的旧写入重放变成空操作同毫秒平局时新写入获胜因为同一仓库的活跃写入被其包锁串行化。这为跨副本、崩溃恢复场景下标签的最终一致性提供了保证。认证docker login pnpr tokenOCI 客户端通过标准的 registry 认证流程登录pnpr 复用其自身的 token 体系docker login pnpr.example.com # Username: 你的 pnpr 用户名 # Password: 你的 pnpr token变更说明明确密码处填 pnpr token。服务端的认证接入点在 pnpr/crates/pnpr/src/server/authentication.rs请求会先尝试按 OCI token 解码pnpr/crates/pnpr/src/server/oci/tokens/ 模块解码失败则走常规认证路径同文件第 346 行 通过检查路径段中是否出现pnpr_oci::API_SEGMENT即v2来识别 OCI 请求。tokens/tests.rs 中的测试展示了 token 的作用域模型claims 携带audience如/oci/~images与scopes如acme/v2/app上的pull/push权限随后按路径与 HTTP 方法逐条判定是否放行。深度实现pnpr 如何存储一个镜像仓库ImageDocument仓库的持久化形状pnpr/crates/oci/src/document.rs 定义了每个镜像仓库的持久化文档ImageDocument包含name仓库名manifests按 digest 排序的 manifest 条目ManifestEntry记录 digest、mediaType、size以及可选的 referrer 元数据tags按标签名排序的TagEntrygeneration代际计数用于隔离显式 blob 删除之前已预备的日志化发布deleting_blob待删除的 blob digest删除完成前会阻止新的发布。层与配置 blob 刻意不记录在文档里它们是内容寻址、不可变、且在有人引用之前就先上传的字节manifest 才是发布动作因此文档只记录 manifest 与 tag。两个集合始终保持有序因为这里的所有查找都是二分查找manifest()、tag()、resolve()均如此。合并语义让事务重放安全merge()document.rs用于把日志化写入合并进已存储文档manifest 内容寻址已存在即同字节、保持不变tag 按时间戳单调合并。generation 不匹配或存在待删除 blob 时拒绝合并。这样被新写入取代的旧日志化写入可以安全重放而不破坏状态。延伸能力referrers、分页、blob 删除与在线回收围绕容器镜像服务仓库中还有多个配套的变更说明与实现可作为实战参考Referrers APIGET /v2/name/referrers/digest列出挂接到某镜像上的工件签名、SBOM、扫描结果等支持artifactType过滤实现位于 pnpr/crates/pnpr/src/server/oci/referrers.rs并在.changeset/pnpr-oci-protocol-surface.md中说明跨仓库 blob 挂载与分段下载跨仓库 blob 挂载复用可读仓库中的层支持 Range 请求下载 blob_catalog与tags/list支持n/last分页见 discovery.rs 与.changeset/pnpr-oci-protocol-surface.md删除与在线 GCDELETE /v2/name/manifests/reference由 deletion.rs 实现与 manifest_request.rs 的删除端点配合通过deleting_blob门闩阻止删除期间的新发布oci-gc离线回收pnpr oci-gc --registry name收集旧的无引用镜像 blob要求先停止该注册表的写入--dry-run可先预览核心逻辑在 pnpr/crates/pnpr/src/oci_maintenance.rs命令入口在 pnpr/crates/pnpr/src/main.rs见.changeset/oci-registry-operations.md跨副本上传恢复使用 S3 存储时跨副本的上传会话可恢复24 小时无活动的废弃共享上传会话在启动时被清理.changeset/oci-registry-operations.md。小结从.changeset/serve-container-images.md出发可以看到pnpr 的容器镜像服务不是另起炉灶而是把 OCI Distribution 协议作为一类新的生态ecosystem: oci接入其既有的注册表路由、访问控制、token 认证与存储体系。对外它是标准的/v2/镜像仓库docker/podman/skopeo开箱即用对内它依靠内容寻址 blob、以 manifest 写入为发布提交点、用时间戳单调合并保证标签的崩溃安全。无论你是想用 pnpr 统一托管内部 npm 包与容器镜像还是希望深入理解 OCI 注册表的工程实现都可以从 pnpr/crates/oci 与 pnpr/crates/pnpr/src/server/oci 这两个目录开始阅读源码。【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

python-pptx 实现《岩石和矿物》PPT 批量生成与 OOXML 校验

python-pptx 实现《岩石和矿物》PPT 批量生成与 OOXML 校验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 16:37:06 阅读更多 →
基于图像识别与BP神经网络的智慧农业灌溉决策系统

基于图像识别与BP神经网络的智慧农业灌溉决策系统

简介:一篇题为《基于图像识别和BP神经网络的灌溉模型的研究》的学术论文PDF,面向农业工程、机器学习及智慧灌溉领域的研究者和从业者,针对传统灌溉模型忽视作物生理状态与气象因素的问题,提出将图像识别、CWSI指数和BP神经网络相结…

2026/9/20 16:36:05 阅读更多 →
PL-300备考练习数据怎么选?Power BI实战数据集获取与用法详解

PL-300备考练习数据怎么选?Power BI实战数据集获取与用法详解

简介:面向微软Power BI PL-300认证考生的官方练习数据包,聚焦数据建模、DAX计算、报表设计与仪表板发布等核心考点,基于AdventureWorks和TailspinToys两种示例业务库展开实操。包体内含94个文件、共56.04MB,既有31个pbix成品报表可…

2026/9/20 16:36:05 阅读更多 →

最新新闻

Vue 3 卡片滑动组件实战:从手势原理到性能优化

Vue 3 卡片滑动组件实战:从手势原理到性能优化

最近在做一个社交类项目的时候,产品提了个需求:首页要有一组用户卡片,可以像现在主流交友软件那样左右滑动,喜欢就右滑,不喜欢就左滑,滑出去的卡片要有抛飞效果,下面的卡片要能跟着顶上来。需求…

2026/9/20 17:13:32 阅读更多 →
Docker + Nginx 反向代理 Node.js 应用:从部署到避坑全指南

Docker + Nginx 反向代理 Node.js 应用:从部署到避坑全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/20 17:13:32 阅读更多 →
Unity微信小游戏全生命周期实战指南

Unity微信小游戏全生命周期实战指南

1. 这不是“云小游戏”的简单叠加,而是研发、运维、运营三股绳拧成一股劲的实战重构我第一次在客户现场听到“腾讯云联合微信小游戏”这个说法时,下意识皱了眉头——又一个厂商把两个热词缝在一起的PPT项目?直到亲眼看着一家做休闲益智类小游…

2026/9/20 17:13:32 阅读更多 →
基于机器学习的Web日志异常检测:从特征工程到CLI工具实践

基于机器学习的Web日志异常检测:从特征工程到CLI工具实践

简介:一款基于机器学习的Web日志统计分析与异常检测命令行工具,面向运维、开发及安全分析人员,可对Web访问日志进行自动化统计与异常行为识别。项目基于Python实现,内置机器学习模型,适合用于项目开发、毕业设计、课程…

2026/9/20 17:13:32 阅读更多 →
FreeSurfer可视化避坑指南:从recon-all到freeview的完整QC流程

FreeSurfer可视化避坑指南:从recon-all到freeview的完整QC流程

1. 为什么recon-all不是终点,而是起点:FreeSurfer流程中被集体忽视的“可视化断层”FreeSurfer在神经影像处理圈子里是个响当当的名字,尤其对做结构MRI分析的研究者来说,recon-all命令几乎成了条件反射——T1图像往里一扔&#xf…

2026/9/20 17:13:32 阅读更多 →
FastGPT 接入企业微信机器人:30 分钟一次跑通企微智能问答

FastGPT 接入企业微信机器人:30 分钟一次跑通企微智能问答

FastGPT 接入企业微信机器人:30 分钟一次跑通企微智能问答 【免费下载链接】FastGPT FastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visua…

2026/9/20 17:12:31 阅读更多 →

日新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/20 0:00:46 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/20 0:00:46 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/20 0:00:46 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →