3. 项目级包仓库的创建与配置
GitLab 的 Package Registry 是实例级能力,但真正承载包的是项目级包仓库。每个 GitLab 项目都拥有独立的包命名空间,包以 项目路径/包名/版本 的形式被寻址。理解这一点非常关键:包仓库不是独立于项目存在的“另一个服务”,而是项目的一个附属存储域,它的可见性、权限、配额都继承自项目本身。因此“创建项目级包仓库”并不是点击一个“新建仓库”按钮,而是在项目中启用 Package Registry 能力,并把它接入到正确的命名空间、权限模型和存储策略中。
一、先理解命名空间与寻址结构
GitLab 的包地址由三层构成:实例域名、项目路径、包坐标。以 Maven 为例,一个包在仓库中的完整坐标大致是:
https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven
groupId: com.example.pay
artifactId: pay-core
version: 1.4.0
其中 groupId 通常与项目路径对齐,例如项目路径为 payment/pay-core,则 groupId 可设为 com.example.payment。这种对齐不是强制的,但强烈建议保持,否则后续在 UI 中按项目筛选包时会非常混乱。项目路径决定了包的“归属命名空间”,而 project_id 是 API 寻址时最稳定的标识——项目改名后路径会变,但 ID 不变,因此 CI 中优先使用 $CI_PROJECT_ID 而非硬编码路径。
二、启用 Package Registry 与可见性配置
在 GitLab 15 及以后版本中,Package Registry 默认对项目启用,无需单独开关。真正需要配置的是项目可见性与包访问权限的联动关系。项目可见性分为 Private、Internal、Public 三档,它直接决定谁能读取包:
- Private 项目:只有项目成员能拉取包,适合内部业务系统。
- Internal 项目:任何登录用户可读,适合公司内部共享的基础库。
- Public 项目:匿名用户也可读,适合开源组件。
需要特别注意的是:包的读取权限跟随项目可见性,但写入权限永远需要 Developer 及以上角色。也就是说,即使项目是 Public,匿名用户也只能下载、不能上传。这一设计避免了公开项目被任意注入包的风险。
三、权限模型:谁能发布、谁能消费
GitLab 项目角色与包操作的对应关系如下表。这张表是配置权限时的核心依据:
| 项目角色 | 拉取包 | 发布包 | 删除包 |
|---|---|---|---|
| Guest | Private 项目不可,Internal/Public 可 | 否 | 否 |
| Reporter | 可 | 否 | 否 |
| Developer | 可 | 可 | 否 |
| Maintainer | 可 | 可 | 可 |
| Owner | 可 | 可 | 可 |
实践中常见的做法是:CI 流水线使用 Project Access Token 或 Deploy Token 发布包,而不是个人令牌。Deploy Token 可以限定为 read_package_registry 或 write_package_registry 单一权限,泄露风险更低。创建路径为:项目 → Settings → Repository → Deploy tokens,勾选 write_package_registry 后生成,得到用户名和令牌两个值。
四、存储配额与命名空间约束
包会占用项目存储配额。GitLab 的存储统计中,Package Registry 单独计一项,可在 项目 → Settings → Usage Quotas 中查看。若实例启用了命名空间存储限制,则同一 group 下所有项目的包总量受 group 配额约束。配置时需关注三点:
- 配额归属:包计入所属项目的存储,而非发布者个人。
- 清理策略:可在 Settings → Packages and Registries 中设置“保留最近 N 个版本”的清理规则,避免快照版本无限堆积。
- 重复包处理:默认不允许覆盖同版本包,重复发布同版本会返回 403,需先删除旧版本或提升版本号。
五、完成第一个项目级包仓库初始化
下面以 Maven 包为例,走通一次完整的初始化。假设项目路径为 payment/pay-core,项目 ID 为 128。
第一步,确认项目已启用包功能。进入项目 → Deploy → Package Registry,若能看到空列表页,说明能力已就绪。
第二步,创建 Deploy Token。在 Settings → Repository → Deploy tokens 中新建,名称 pkg-writer,勾选 write_package_registry,保存后记录用户名与令牌。
第三步,配置本地 Maven 的 settings.xml。把令牌写入 server 配置,避免明文出现在 pom 中:
<settings>
<servers>
<server>
<id>gitlab-pay-core</id>
<username>pkg-writer</username>
<password>glpat-xxxxxxxxxxxx</password>
</server>
</servers>
</settings>
第四步,在 pom.xml 中声明发布地址。注意 URL 使用项目 ID 而非路径,更稳定:
<distributionManagement>
<repository>
<id>gitlab-pay-core</id>
<url>https://gitlab.example.com/api/v4/projects/128/packages/maven</url>
</repository>
<snapshotRepository>
<id>gitlab-pay-core</id>
<url>https://gitlab.example.com/api/v4/projects/128/packages/maven</url>
</snapshotRepository>
</distributionManagement>
第五步,执行发布并验证。运行 mvn deploy,控制台出现 Uploaded to gitlab-pay-core 即表示上传成功。随后回到项目 Package Registry 页面,应能看到 com.example.pay:pay-core:1.4.0 条目,点击可查看文件列表与校验和。
消费端只需在 pom.xml 中声明同样的 repository 地址,并在 settings.xml 中配置只读令牌即可拉取。至此,一个项目级包仓库完成了从启用、授权、发布到验证的闭环。
回看整个初始化过程,真正决定成败的不是某条命令,而是三件事是否对齐:项目路径与包坐标是否一致、令牌权限是否最小化、配额与清理策略是否提前设定。把这三件事在项目创建初期就固定下来,后续几十个包接入时就不会出现命名混乱、权限外溢或存储爆满的问题。