2. GitLab包与制品库体系总览
GitLab 的制品管理能力并不是单一功能,而是由多个注册表(Registry)组件拼装成的一套体系。理解这套体系的关键,不是记住每个组件的名字,而是先分清它们各自“管什么对象、解决什么协议、在什么场景下被谁调用”。本节围绕 Package Registry、Container Registry、Dependency Proxy 与 Infrastructure Registry 四个核心组件,梳理它们的能力边界与协同关系。
一、四个组件各自管理什么对象
Package Registry 面向的是“语言生态的包”。它支持 npm、Maven、PyPI、NuGet、Composer、Conan、RubyGems、Generic 等多种格式,本质上是把 GitLab 当作一个多协议的包仓库服务器。开发者用 npm publish、mvn deploy、twine upload 等原生工具,把包推送到某个项目的 Package Registry 中,再通过对应的 .npmrc、settings.xml、pip.conf 等配置从同一位置拉取。它的核心价值是:让私有包和公共包使用同一套认证与权限模型,避免自建 Nexus/Artifactory 的额外运维。
Container Registry 面向的是“OCI 镜像与制品”。它遵循 OCI Distribution 规范,支持 docker push/pull、podman、buildah 等标准客户端。镜像按 registry.example.com/<namespace>/<project>/<image>:<tag> 的路径组织,权限继承 GitLab 项目成员权限。除容器镜像外,它也能存放 Helm Chart、OCI Artifact 等符合 OCI 规范的制品,是 CI/CD 流水线中构建产物最主要的落地点。
Dependency Proxy 面向的是“上游公共仓库的拉取代理”。它本身不生产包,而是为 npm、Maven、PyPI 等格式提供一个缓存层:当流水线或开发者请求一个公共包时,GitLab 先查本地缓存,未命中则回源到 npmjs.org、Maven Central、pypi.org 等上游拉取并缓存。它的价值在于减少对外网出口的依赖、加速重复拉取、并在上游不可用时提供一定缓冲。
Infrastructure Registry 面向的是“基础设施即代码的模块与状态”。它主要服务于 Terraform:可以托管 Terraform Module(模块仓库)和 Terraform State(状态文件后端)。模块仓库让团队以版本化方式复用 .tf 模块;State 后端则把 terraform.tfstate 集中存储并加锁,替代本地文件或自建 S3 后端,使多人协作的 Terraform 流程具备一致的状态来源。
二、能力边界:什么该放哪里
四个组件最容易混淆的地方,是“一个制品到底该进哪个库”。判断依据可以归结为两条:制品的消费协议,以及制品的生命周期归属。
如果制品要被 npm install、mvn dependency:get、pip install 这类包管理器直接解析,它属于 Package Registry。如果制品要被容器运行时或编排系统以镜像方式拉取,它属于 Container Registry。如果制品是 Terraform 的模块或状态文件,它属于 Infrastructure Registry。Dependency Proxy 不接收主动推送,它只在上游拉取路径上被动缓存,因此不存在“把包推到 Dependency Proxy”这种操作。
一个常见的误区是把容器镜像也推到 Package Registry 的 Generic 包里。这样做虽然能存,但失去了 OCI 的层复用、摘要校验和 docker pull 兼容性,后续无法被 K8s 直接消费。因此镜像应始终走 Container Registry,Generic 包只用于那些没有专属协议、又需要版本化分发的文件,例如二进制工具、安装包、模型文件。
三、协同关系:一条流水线里的分工
把四个组件放进一条典型 CI/CD 流水线,协同关系会更清楚。假设一个 Node.js 服务项目,流水线大致经历以下阶段:
- 依赖安装:Runner 执行
npm ci。若项目配置了 Dependency Proxy,公共包从代理缓存拉取;私有包从 Package Registry 拉取。两者使用同一个CI_JOB_TOKEN认证。 - 构建与测试:产出
dist/目录与测试报告。 - 镜像构建与推送:
docker build后docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA,镜像进入 Container Registry。 - 包发布:若该项目同时是一个可复用库,执行
npm publish把包推入 Package Registry,供其他项目依赖。 - 基础设施变更:若涉及 Terraform,
terraform init从 Infrastructure Registry 拉取模块,terraform apply把 State 写回同一注册表。
可以看到,四个组件共享同一套项目权限、同一套 Token 体系(CI_JOB_TOKEN、Personal Access Token、Deploy Token),但各自处理不同协议、不同生命周期的对象。这种“统一认证、分协议存储”的设计,正是 GitLab 制品体系相对独立仓库方案的核心差异。
四、认证与权限的共性
无论访问哪个注册表,认证方式基本一致。CI 环境中推荐使用 CI_JOB_TOKEN,它随流水线自动注入,权限限定在当前项目;跨项目拉取时可在目标项目设置 Job Token 允许列表。人工操作或外部系统则使用 Personal Access Token 或 Deploy Token,后者适合只读拉取场景,可限定到具体项目与注册表范围。
# 以 Container Registry 为例,CI 中登录并推送
docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
# 以 Package Registry 为例,发布 npm 包
npm config set @myorg:registry https://gitlab.example.com/api/v4/projects/<id>/packages/npm/
npm config set //gitlab.example.com/api/v4/projects/<id>/packages/npm/:_authToken $CI_JOB_TOKEN
npm publish
五、选型与组合建议
对于中小团队,建议至少启用 Package Registry 与 Container Registry,前者承载私有库,后者承载镜像。若外网出口受限或拉取频繁,再叠加 Dependency Proxy。Infrastructure Registry 则在使用 Terraform 且需要多人共享 State 时启用,否则可暂不引入。
需要留意的是,Dependency Proxy 的缓存有容量与过期策略,不能当作永久存储;Container Registry 的镜像清理需要配置保留策略,否则存储会持续增长;Package Registry 的包删除会影响依赖它的项目,删除前应确认引用关系。这些边界决定了四个组件不是“越多越好”,而是按实际消费路径组合使用。