pnpm 的 pnpr 私有仓库:用oci.maxBlobBytes与oci.maxManifestBytes精细控制 OCI 推送大小
【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm
pnpr 是 pnpm 仓库中附带的 registry 服务器(兼容 verdaccio 配置格式),其 OCI Distribution 接口用于托管镜像与制品。@pnpm/pnpr的 minor 版本更新(见 .changeset/pnpr-oci-size-limits.md)将 OCI blob 与 manifest 的大小上限从硬编码改为可通过oci.maxBlobBytes和oci.maxManifestBytes两个配置项调节。读完本文,你将掌握这两个配置项的语义、默认值与底层校验行为,能够为私有 pnpr 部署定制镜像推送上限。
两个配置项是什么
在 pnpr 的 YAML 配置文件中,oci是一个 pnpr 专有的顶层块,与storage、registries等并列,用于配置 OCI Distribution 表面的认证与字节上限:
oci: maxBlobBytes: 10737418240 maxManifestBytes: 4194304字段含义如下:
| 配置项 | 类型 | 默认值 | 作用 |
|---|---|---|---|
maxBlobBytes | 整数(字节) | 10 * 1024 * 1024 * 1024(10 GiB) | 单个 blob(镜像层)的最大字节数 |
maxManifestBytes | 整数(字节) | 4 * 1024 * 1024(4 MiB) | 单个 manifest(含其引用)的最大字节数 |
在 pnpr/crates/config/src/lib.rs 中,OciConfig结构体使用#[serde(rename_all = "camelCase", deny_unknown_fields)]反序列化,因此配置文件里必须使用 camelCase 写法maxBlobBytes/maxManifestBytes(而非 snake_case)。若未配置该块,Default实现会回退到上述默认值。
如何配置
在 pnpr 的config.yaml中加入oci块即可覆盖默认值:
oci: maxBlobBytes: 10737418240 # 允许单个层最大 10 GiB maxManifestBytes: 4194304 # 允许单个 manifest 最大 4 MiB参考官方文档 pnpr/crates/pnpr/README.md:默认情况下,一个层最多 10 GiB、一个 manifest 最多 4 MiB;通过上面的 YAML 可配置为正字节限制。
注意配置校验:在 pnpr/crates/config/src/config_file.rs 的parse_config_file中,解析后若max_blob_bytes == 0或max_manifest_bytes == 0,会直接返回RegistryError::InvalidConfig,错误信息为oci size limits must be greater than zero,即两个上限必须大于 0,配置为 0 会被拒绝启动。对应行为测试见 pnpr/crates/config/src/tests/behavior.rs。
底层行为:blob 大小限制如何生效
maxBlobBytes的校验贯穿 blob 上传的完整生命周期。在 pnpr/crates/pnpr/src/server/oci/upload_session.rs 中:
- 单请求/分块上传:
start_upload、append_chunk、complete_upload都会调用append_body(..., self.state.inner.config.http.oci.max_blob_bytes),流式追加时持续校验,一旦超过限制即中止上传并返回拒绝响应(上传会话会被abort_blob_upload清理)。 - 断点续传:
check_chunk_start会对Content-Range声明的跨度做校验,if span > limit时返回SizeInvalid错误,提示a blob may not exceed {limit} bytes;同时校验Content-Length与Content-Range是否一致。 - 跨仓库 blob 挂载(mount):
mount_blob在从源仓库复用层时同样应用max_blob_bytes,超出则拒绝并中止目标上传。
由文档 pnpr/crates/pnpr/README.md 可知:该限制作用于整个可断点续传的上传过程(包括挂载的层),同时也会约束未缓存的 upstream 下载。blob 上传是流式写入磁盘而非整体驻留内存,并在落盘前按客户端承诺的 digest 校验。
底层行为:manifest 大小限制如何生效
maxManifestBytes主要约束 manifest 的写入与读取:
- 写入:在 pnpr/crates/pnpr/src/server/oci/manifest_request.rs 的
manifest_publication中,请求体通过collect_body(body, max_manifest_bytes)收集,超过上限即拒绝;随后OciPublication::new也携带该上限再次校验。 - 读取:
read_manifest用read_manifest_bytes(..., max_manifest_bytes)从存储读回 manifest,避免超限数据被加载进内存。 - referrers 分页:在 pnpr/crates/pnpr/src/server/oci/referrer_page.rs 中,referrers 响应页面会累计响应字节,若加上下一个 descriptor 后超过
max_manifest_bytes则停止分页,防止单个响应膨胀超过 manifest 上限(referrers.rs 中以此创建页面对象)。 - 删除与维护:
deletion.rs与oci_maintenance.rs也复用该上限读取/解析 manifest,保证删除记录与 GC 收集逻辑与配置保持一致。
从文档 pnpr/crates/pnpr/README.md 可知,manifest 写入是发布变为可见的临界点:它与其他生态一样经过发布日志,要么整体落盘、要么不留痕迹;未被任何 manifest 引用的 blob 对客户端不可见(半发布状态不存在),未引用的 blob 会累积直到被 GC 回收。
实践建议
- 若你的团队会推送包含大模型权重或大二进制层的镜像,可适当调高
maxBlobBytes(注意单位为字节,如 20 GiB 写作21474836480)。 - 若 manifest 携带大量 attestation / referrer 描述符,可调高
maxManifestBytes,避免分页截断导致客户端拉取不完整。 - 两个值都必须为正整数;配置为
0或负数会在启动时被 parse_config_file 拒绝。 - 由于
deny_unknown_fields,oci块内不能出现拼写错误的键名(如maxBlobSize),否则反序列化失败并报配置错误。
pnpr 通过这两个配置项把 OCI 表面的大小策略交给部署者,既保留默认的宽松上限,又能在受限环境中收紧资源使用,是镜像仓库运维中值得关注的可调项。
【免费下载链接】pnpmFast, disk space efficient package manager项目地址: https://gitcode.com/gh_mirrors/pn/pnpm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考