GitLab Container Registry
文档用途
介绍 GitLab Container Registry, 包括主要的使用场景和最佳实践.
写在前面
Container Registry 可以直译为 "容器注册 (服务)", 我们也可以称之为 "镜像仓库".
类似于 Docker Hub, GitLab Container Registry 提供了容器镜像的上传下载的服务.
相比于 Docker Hub 默认公开, GitLab Container Registry 默认私有.
网页入口
代码仓库的 Deploy / Container Registry 页面:

如果找不到以上页面, 可能是代码仓库没有启用这个 Feature.
可以通过代码仓库 Settings / Gerneral 页面中的开关来启用:

CI/CD Job
简单示例
显然我们希望在 CI/CD 中构建镜像后, 自动将其上传至 Container Registry.
这非常容易实现, 因为 GitLab 为我们提供了相关的 预定义环境变量.
# 这里所有的环境变量都是预定义的
build-and-push-to:
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE .
- docker push $CI_REGISTRY_IMAGE最佳实践
以上只是简单的演示, 实际的的 CI/CD Job 会更复杂一些:
- 设计合理的标签 (image tag) 策略.
- 使用
--quiet来减少日志中的噪音. - 通过
tag字段来筛选恰当的 gitlab-runner. - 通过
stage和needs字段配置执行顺序. - 考虑将构建与上传分成不同的 CI/CD Job.
访问权限
个人账户
若有代码仓库的开发者权限, 则可以使用自己的账户密码来访问 Container Registry.
需要注意, 如果个人账户启用了 两步验证, 则需要创建 Personal Access Token.

自动化流程
在自动化流程中, 例如 k8s 集群中部署服务时, 为了避免个人账户密码泄露所造成的灾难性后果,
建议使用 Deploy Tokens, 实现 k8s 中私有镜像仓库的授权.
清理策略
配置页面
INFO
启用 Cleanup Policies 后, GitLab 会周期性地检查需要被清理的镜像, 以免镜像占用太多空间.
在代码仓库的 Settings / Packages and registries 页面, 可以配置清理策略.

在用正则表达式描述清理策略是, 注意 不要 包含开头的 ^ 和结尾的 $.
例如 v.+ 可以匹配所有以 v 开头的镜像标签, 不需要写成 ^v.+$.
如果希望匹配满足 Semantic Versioning 的镜像标签 (详见 regex101), 可以这么写:
(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?设计思路
"清理策略" 应该与 "镜像标签策略" 联系到一起来做设计, 这里提供一个简单的思路:
镜像标签策略:
- 每次构建镜像时, 都使用 commit sha 来作为标签, 例如
8c5ce85. - 每次通过 Merge Request 中的 Job 构建时, 使用 MR 的 ID, 例如
mr-66. - 每次新增 Git Tag 时 (会自动触发 CI/CD), 使用 Git Tag 作为镜像标签, 例如
0.5.8. - 通过 Git Tag 出发的 CI/CD 构建的镜像, 也使用
latest作为标签.
Git Tag 在这个思路中非常重要, 应严格遵守 Semantic Versioning.
清理策略:
- 保留最近上传的 10 个镜像.
- 保留所有以 Git Tag 作为标签的镜像 (也就是满足 Semantic Versioning 的标签).
- 每 30 天清理所有标签 (那些 "满足被保留要求的标签" 不会被删除).
常见问题
镜像大小为零
如果遇到下图中的问题 (镜像大小为 0 bytes), 多半是因为 构建了多平台的容器镜像.

GitLab Container Registry 是支持多平台镜像的, 但目前还不够完美, 需要我们调整构建命令.
在构建命令中加入 --provenance false 即可. 完整的构建命令举例:
docker build -t $IMAGE_TAG . \
--platform linux/amd64,linux/arm64 \
--provenance false \
--quiet