- 查看 Container Registry
- 使用来自 Container Registry 的镜像
- 镜像命名约定
- 使用 Docker 命令构建和推送镜像
- 使用 GitLab CI/CD 构建和推送
- 删除镜像
- 清理策略
- 限制
- 为项目禁用 Container Registry
- 更改 Container Registry 的可见性
- Container Registry 可见性权限
- Manifest 列表和垃圾回收
- GitLab Container Registry 故障排查
GitLab Container Registry
通过将 Docker Container Registry 集成到极狐GitLab 中,每个极狐GitLab 项目都可以拥有自己的空间来存储其 Docker 镜像。
您可以在 https://docs.docker.com/registry/introduction/ 阅读有关 Docker Registry 的更多信息。
本文档是用户指南。要了解如何为您的极狐GitLab 实例启用容器镜像库,请访问管理员文档。
查看 Container Registry
您可以查看项目或群组的 Container Registry。
- 转到您的项目或群组。
- 转至 软件包与镜像库 > 容器镜像库。
您可以在此页面上搜索、排序、过滤和删除容器。您可以通过从浏览器复制 URL 来共享过滤视图。
只有项目或群组的成员才能访问私有项目的 Container Registry。
如果项目是公开的,那么 Container Registry 也是公开的。
使用来自 Container Registry 的镜像
要下载并运行托管在 GitLab Container Registry 中的容器镜像:
- 将链接复制到您的容器镜像:
- 转到您的项目或群组的 软件包与镜像库 > 容器镜像库 并找到您想要的镜像。
- 在镜像名称旁边,单击 复制 按钮。
-
将
docker run
与镜像链接一起使用:docker run [options] registry.example.com/group/project/image [arguments]
有关运行 Docker 容器的更多信息,请访问 Docker 文档。
镜像命名约定
镜像遵循以下命名约定:
<registry URL>/<namespace>/<project>/<image>
例如,如果您的项目是 gitlab.example.com/mynamespace/myproject
,那么您的镜像必须至少命名为 gitlab.example.com/mynamespace/myproject/my-app
。
您可以将其他名称附加到镜像名称的末尾,深度最多为三层。
例如,这些都是名为 myproject
的项目中镜像的所有有效镜像名称:
registry.example.com/mynamespace/myproject:some-tag
registry.example.com/mynamespace/myproject/image:latest
registry.example.com/mynamespace/myproject/my/image:rc1
使用 Docker 命令构建和推送镜像
要构建并推送到 Container Registry,您可以使用 Docker 命令。
使用 Container Registry 进行身份验证
在构建和推送镜像之前,您必须通过 Container Registry 进行身份验证。
要进行身份验证,您可以使用:
- 个人访问令牌。
- 部署令牌。
这两者都要求最小范围是:
- 对于读(拉取)访问,
read_registry
。 - 对于写(推送)访问,
write_registry
。
要进行身份验证,请运行 docker
命令。 例如:
docker login registry.example.com -u <username> -p <token>
使用 Docker 命令构建和推送镜像
要构建并推送到 Container Registry:
-
使用 Container Registry 进行身份验证。
-
运行命令构建或推送。例如,要构建:
docker build -t registry.example.com/group/project/image .
或者推送:
docker push registry.example.com/group/project/image
要查看这些命令,请转到您项目的 软件包与镜像库 > 容器镜像库。
使用 GitLab CI/CD 构建和推送
使用 GitLab CI/CD 构建镜像并将其推送到容器镜像库。使用它可以从您创建的 Docker 镜像测试、构建和部署您的项目。
使用 GitLab CI/CD 进行身份验证
在使用 GitLab CI/CD 构建和推送镜像之前,您必须通过 Container Registry 进行身份验证。
要使用 CI/CD 进行身份验证,您可以使用:
-
CI_REGISTRY_USER
CI/CD 变量。此变量具有对 Container Registry 的读写访问权限,并且仅对一项作业有效。它的密码也会自动创建并分配给
CI_REGISTRY_PASSWORD
。docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
-
CI 作业令牌。
docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
-
部署令牌最小范围为:
- 对于读(拉取)访问,
read_registry
。 - 对于写(推送)访问,
write_registry
。
docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
- 对于读(拉取)访问,
-
个人访问令牌 的最小范围为:
- 对于读(拉取)访问,
read_registry
。 - 对于写(推送)访问,
write_registry
。
docker login -u <username> -p <access_token> $CI_REGISTRY
- 对于读(拉取)访问,
配置您的 .gitlab-ci.yml
文件
您可以配置您的 .gitlab-ci.yml
文件来构建镜像并将其推送到 Container Registry。
- 如果多个作业需要身份验证,请将身份验证命令放在
before_script
中。 - 在构建之前,使用
docker build --pull
来获取对基础镜像的更改。它需要稍长的时间,但它可以确保您的镜像是最新的。 - 在每次
docker run
之前,执行一个显式的docker pull
来获取刚刚构建的镜像。如果您使用多个在本地缓存镜像的 runner,这一点尤其重要。 如果您在镜像标签中使用 Git SHA,则每个作业都是独一无二的,您永远不应拥有过期的镜像。但是,如果在依赖项更改后重新构建给定的提交,仍然可能有一个陈旧的镜像。 - 不要直接构建到
latest
标签,因为多个作业可能同时发生。
GitLab CI/CD 的 Container Registry 示例
如果您在 runner 上使用 Docker-in-Docker,.gitlab-ci.yml
应该是:
build:
image: docker:19.03.12
stage: build
services:
- docker:19.03.12-dind
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY/group/project/image:latest .
- docker push $CI_REGISTRY/group/project/image:latest
您还可以使用其他 CI/CD 变量来避免硬编码:
build:
image: docker:19.03.12
stage: build
services:
- docker:19.03.12-dind
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
在这里,$CI_REGISTRY_IMAGE
将被解析为与该项目相关联的库的地址。由于 $CI_COMMIT_REF_NAME
解析为分支或标签名称,并且您的分支名称可以包含正斜杠(例如,feature/my-feature
),所以使用 $CI_COMMIT_REF_SLUG
作为镜像标签会更安全。这是因为镜像标签不能包含正斜杠。我们还声明了我们自己的变量 $IMAGE_TAG
,将两者结合起来以节省我们在 script
部分中的一些输入。
这是一个更详细的示例,它将任务分成 4 个搜了下阶段,包括两个并行运行的测试。build
存储在容器镜像库中,供后续阶段使用,在需要时下载镜像。 对 main
的更改也被标记为 latest
并使用特定于应用程序的部署脚本进行部署:
image: docker:19.03.12
services:
- docker:19.03.12-dind
stages:
- build
- test
- release
- deploy
variables:
# Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
build:
stage: build
script:
- docker build --pull -t $CONTAINER_TEST_IMAGE .
- docker push $CONTAINER_TEST_IMAGE
test1:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/tests
test2:
stage: test
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test
release-image:
stage: release
script:
- docker pull $CONTAINER_TEST_IMAGE
- docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
- docker push $CONTAINER_RELEASE_IMAGE
only:
- main
deploy:
stage: deploy
script:
- ./deploy.sh
only:
- main
docker pull
。如果您更喜欢使用 image:
隐式拉取构建的镜像,并使用 Docker 或 Kubernetes executor,确保 pull_policy
设置为 always
。使用 Container Registry 中的 Docker-in-Docker 镜像
要将您自己的 Docker 镜像用于 Docker-in-Docker,除了 Docker-in-Docker 部分中的步骤之外,还请按照以下步骤操作:
- 更新
image
和service
以指向您的镜像库。 - 添加服务别名。
下面是 .gitlab-ci.yml
的例子:
build:
image: $CI_REGISTRY/group/project/docker:19.03.12
services:
- name: $CI_REGISTRY/group/project/docker:19.03.12-dind
alias: docker
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
如果忘记设置服务别名,docker:19.03.12
镜像无法找到 dind
服务,会抛出类似如下错误:
error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host
使用带有 Dependency Proxy 的 Docker-in-Docker 镜像
要将您自己的 Docker 镜像与 Dependency Proxy 一起使用,除了 Docker-in-Docker 部分中的步骤之外,还请按照以下步骤操作:
- 更新
image
和service
以指向您的镜像库。 - 添加服务别名。
下面是 .gitlab-ci.yml
的例子:
build:
image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:19.03.12
services:
- name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:18.09.7-dind
alias: docker
stage: build
script:
- docker build -t my-docker-image .
- docker run my-docker-image /script/to/run/tests
如果忘记设置服务别名,docker:19.03.12
镜像无法找到 dind
服务,会抛出类似如下错误:
error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host
删除镜像
您可以通过多种方式从 Container Registry 中删除镜像。
在自助管理的实例上,删除镜像不会释放存储空间 - 它只会将镜像标记为可以删除。要实际删除镜像并恢复存储空间,以防它们未被引用,管理员必须运行垃圾收集。
从极狐GitLab 中删除镜像
从极狐GitLab 中删除镜像:
- 导航到您的项目或群组的 软件包与镜像库 > 容器镜像库。
-
在 容器镜像库 页面,您可以通过以下任一方式选择要删除的内容:
- 通过单击红色的 Trash 图标删除整个仓库及其包含的所有标签。
- 导航到仓库,并通过单击要删除的标签旁边的红色 Trash 图标来单独或批量删除标签。
- 在对话框中,单击 删除标签。
使用 GitLab CI/CD 删除镜像
以下示例定义了两个阶段:build
和 clean
。build_image
作业为分支构建 Docker 映像,delete_image
作业将其删除。下载 reg
可执行文件并用于删除与 $CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG
预定义 CI/CD 变量 匹配的镜像。
要使用此示例,请更改 IMAGE_TAG
变量以满足您的需要:
stages:
- build
- clean
build_image:
image: docker:19.03.12
stage: build
services:
- docker:19.03.12-dind
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
only:
- branches
except:
- main
delete_image:
image: docker:19.03.12
stage: clean
services:
- docker:19.03.12-dind
variables:
IMAGE_TAG: $CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG
REG_SHA256: ade837fc5224acd8c34732bf54a94f579b47851cc6a7fd5899a98386b782e228
REG_VERSION: 0.16.1
before_script:
- apk add --no-cache curl
- curl --fail --show-error --location "https://github.com/genuinetools/reg/releases/download/v$REG_VERSION/reg-linux-amd64" --output /usr/local/bin/reg
- echo "$REG_SHA256 /usr/local/bin/reg" | sha256sum -c -
- chmod a+x /usr/local/bin/reg
script:
- /usr/local/bin/reg rm -d --auth-url $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $IMAGE_TAG
only:
- branches
except:
- main
reg
版本,然后通过更改 delete_image
作业中定义的 REG_SHA256
和 REG_VERSION
变量来更新代码示例。使用清理策略删除镜像
您可以为每个项目创建一个清理策略,以确保定期从 Container Registry 中删除较旧的标签和镜像。
清理策略
清理策略是一项计划作业,可用于从 Container Registry 中删除标签。 对于定义它的项目,匹配正则表达式 pattern 的标签将被删除。 底层镜像层和镜像保留。
管理员可以使用垃圾收集与 -m
开关。
启用清理策略
清理策略可以在所有项目上运行,但以下情况除外:
-
对于自助管理实例,项目必须是在 12.8 或更高版本中创建的。 但是,管理员可以通过设置
container_expiration_policies_enable_historic_entries
为 true,在 GitLab 应用程序设置中为所有项目(甚至是 12.8 之前创建的项目)启用清理策略。 或者,您可以在 Rails 控制台中执行以下命令:ApplicationSetting.last.update(container_expiration_policies_enable_historic_entries: true)
如果为所有项目启用,可能存在性能风险,特别是如果您使用外部镜像库。
-
对于自助管理实例,您可以为特定项目启用或禁用清理策略。
要启用:
Feature.enable(:container_expiration_policies_historic_entry, Project.find(<project id>))
要禁用:
Feature.disable(:container_expiration_policies_historic_entry, Project.find(<project id>))
清理策略工作原理
清理策略会收集 Container Registry 中的所有标签并排除标签,直到只剩下要删除的标签为止。
清理策略根据标签名称搜索镜像。对完整路径的支持尚未实现,但允许您清理动态命名的标签。
清理策略:
- 在列表中收集给定仓库的所有标签。
- 从列表中排除名为
latest
的标签。 - 评估
name_regex
(要过期的标签),从列表中排除不匹配的名称。 - 从列表中排除任何与
name_regex_keep
值匹配的标签(要保留的标签)。 - 排除任何没有 manifest 的标签(不是 UI 中选项的一部分)。
- 按
created_date
对剩余标签进行排序。 - 根据
keep_n
值(要保留的标签数)从列表中排除 N 个标签。 - 从列表中排除比
older_than
值(过期间隔)更新的标签。 - 最后,将列表中剩余的标签从 Container Registry 中删除。
创建清理策略
您可以在 API 或 UI 中创建清理策略。
要在 UI 中创建清理策略:
- 对于您的项目,转到 设置 > 软件包与镜像库。
- 展开 清理镜像标签 部分。
-
填写字段。
字段 描述 切换 打开或关闭策略。 运行清理 策略应该多久运行一次。 保留最近的 总是为每个镜像保留多少标签。 保留匹配标签 确定要保留哪些标签的正则表达式 pattern。 latest
标签总是被保留。对于所有标签,使用.*
。请参阅其他 regex pattern 示例。删除早于以下时间的标签 仅删除早于 X 天的标签。 删除匹配的标签 确定要删除哪些标签的正则表达式 pattern。该值不能为空。对于所有标签,使用 .*
。请参阅其他 regex 模式示例。 - 点击 保存。
根据您选择的时间间隔,策略将被安排运行。
正则表达式 pattern 示例
清理策略使用正则表达式 pattern 来确定应在 UI 和 API 中保留或删除哪些标签。
正则表达式 pattern 会自动用 \A
和 \Z
锚点包围。不要在正则表达式模式中包含任何 \A
、\Z
、^
或 $
标记,因为它们不是必需的。
以下是您可能想要使用的正则表达式 pattern 示例:
-
匹配所有标签:
.*
这是到期正则表达式的默认值。
-
匹配以
v
开头的标签:v.+
-
只匹配名为
main
的标签:main
-
匹配已命名或以
release
开头的标签:release.*
-
匹配以
v
开头、名为main
或以release
开头的标签:(?:v.+|main|release.*)
设置清理限制以节约资源
- 引入于 13.9 版本。
- 部署在功能标志后,默认禁用
- 不推荐用于生产。
- 要在自助管理实例中使用它,请要求管理员启用。
清理策略作为后台进程执行。此过程很复杂,根据要删除的标签数量,该过程可能需要一些时间才能完成。
为了防止服务器资源匮乏,可以使用以下应用程序设置:
-
container_registry_expiration_policies_worker_capacity
。并发运行的最大清理 worker 数。必须大于1
。我们建议从一个较低的数字开始,并在监控后台工作人员使用的资源后增加它。 -
container_registry_delete_tags_service_timeout
。清除过程删除一批标签所需的最长时间(以秒为单位)。 -
container_registry_cleanup_tags_service_max_list_size
。在单次执行中可以删除的最大标签数,必须在另一个执行中删除其他变量。我们建议从一个较低的数字开始,比如100
,并在监控容器镜像被正确删除后增加它。
对于自助管理实例,可以在 Rails 控制台中更新这些设置:
ApplicationSetting.last.update(container_registry_expiration_policies_worker_capacity: 3)
或者,一旦限制被启用,它们在管理中心可用:
- 在顶部栏上,选择 菜单 > 管理员。
- 进入 设置 > CI/CD > 容器镜像库。
启用或禁用清理策略限制
清理策略限制正在开发中,尚未准备好用于生产。它们部署在默认禁用的功能标志后面。可以访问 GitLab Rails 控制台的管理员可以启用。
要启用:
Feature.enable(:container_registry_expiration_policies_throttling)
要禁用:
Feature.disable(:container_registry_expiration_policies_throttling)
使用清理策略 API
您可以使用 GitLab API 设置、更新和禁用清理策略。
示例:
-
选择所有标签,每个镜像至少保留 1 个标签,清理任何超过 14 天的标签,每月运行一次,保留名称为
main
的所有镜像并启用策略:curl --request PUT --header 'Content-Type: application/json;charset=UTF-8' --header "PRIVATE-TOKEN: <your_access_token>" \ --data-binary '{"container_expiration_policy_attributes":{"cadence":"1month","enabled":true,"keep_n":1,"older_than":"14d","name_regex":"","name_regex_delete":".*","name_regex_keep":".*-main"}}' \ "https://gitlab.example.com/api/v4/projects/2"
使用 API 时 cadence
的有效值为:
-
1d
(每天) -
7d
(每周) -
14d
(每两周) -
1month
(每月) -
3month
(每季度)
与外部容器镜像库一起使用
使用外部容器镜像库时,在项目上运行清理策略可能会有一些性能风险。 如果一个项目运行一项删除数千个标签的策略,则后台作业可能会被备份或完全失败。 如果您确信要清理的标签数量最少,建议您只为 12.8 之前创建的项目启用容器清理策略。
清理策略故障排查
如果您看到以下消息:
“更新清理策略时出错。”
检查正则表达式 pattern 以确保它们有效。
极狐GitLab 在清理策略中使用 RE2 语法 作为正则表达式。您可以使用 regex101 regex tester 测试它们。 查看一些常见的 regex 模式示例。
限制
- 推送镜像后,不支持移动或重命名现有的 Container Registry 仓库,因为镜像存储在与仓库路径匹配的路径中。要使用 Container Registry 移动或重命名仓库,您必须删除所有现有镜像。
- 在 12.10 版本之前,清理策略不会删除使用与
latest
标签相同的镜像 ID 的任何标签。
为项目禁用 Container Registry
默认情况下启用容器镜像库。
但是,您可以删除项目的 Container Registry:
- 转到您项目的 设置 > 常规 页面。
- 展开可见性、项目功能、权限部分并禁用Container Registry。
- 单击保存更改。
软件包与镜像库 > 容器镜像库 条目从项目的侧边栏中删除。
更改 Container Registry 的可见性
引入于 14.2 版本。
默认情况下,每个有权访问项目的人都可以看到 Container Registry。 但是,您可以更改项目的 Container Registry 的可见性。
有关此设置授予用户的权限的更多详细信息,请参阅 Container Registry 可见性权限。
- 转到您项目的 设置 > 通用 页面。
- 展开可见性、项目功能、权限部分。
-
在 容器镜像库 下,从下拉列表中选择一个选项:
-
具有访问权限的任何人(默认):Container Registry 对所有有权访问项目的人可见。如果项目是公开的,那么 Container Registry 也是公开的。如果项目是内部的或私有的,那么 Container Registry 也是内部的或私有的。
-
仅项目成员:Container Registry 仅对具有报告者角色或更高角色的项目成员可见。这类似于将 Container Registry 可见性设置为 具有访问权限的任何人 的私有项目的行为。
-
- 选择 保存修改。
Container Registry 可见性权限
查看 Container Registry 和拉取镜像的能力由 Container Registry 的可见性权限控制。您可以通过 UI 上的可见性设置 或 API 更改。其它权限如更新 Container Registry、推送或删除镜像等不受此设置影响。但是,禁用 Container Registry 会禁用所有 Container Registry 操作。
匿名 (互联网上的任何人) | Guest | 报告者、开发者、维护者和所有者 | ||
---|---|---|---|---|
具有 Container Registry 可见性的公开项目 设置为 具有访问权限的任何人 (UI) 或 enabled (API)
| 查看容器镜像库 并拉取镜像 | Yes | Yes | Yes |
具有 Container Registry 可见性的公开项目 设置为 仅项目成员 (UI) 或 private (API)
| 查看容器镜像库 并拉取镜像 | No | No | Yes |
具有 Container Registry 可见性的内部项目 设置为 具有访问权限的任何人 (UI) 或 enabled (API)
| 查看容器镜像库 并拉取镜像 | No | Yes | Yes |
具有 Container Registry 可见性的内部项目 设置为 仅项目成员 (UI) 或 private (API)
| 查看容器镜像库 并拉取镜像 | No | No | Yes |
具有 Container Registry 可见性的私有项目 设置为 具有访问权限的任何人 (UI) 或 enabled (API)
| 查看容器镜像库 并拉取镜像 | No | No | Yes |
具有 Container Registry 可见性的私有项目 设置为 仅项目成员 (UI) 或 private (API)
| 查看容器镜像库 并拉取镜像 | No | No | Yes |
容器镜像库设置为 disabled 的任何项目
| Container Registry 上的所有操作 | No | No | No |
Manifest 列表和垃圾回收
Manifest 列表通常用于创建多架构镜像。如果您依赖 manifest 列表,则应标记由其各自仓库中的列表引用的所有单个 manifest,而不仅仅是 manifest 列表本身。只要至少有一个标记指向它们,可确保这些 manifest 不会被作为垃圾收集。
GitLab Container Registry 故障排查
Docker 连接错误
当群组、项目或分支名称中存在特殊字符时,可能会发生 Docker 连接错误。特殊字符可以包括:
- 前导下划线
- 尾随连字符/破折号
要解决此问题,您可以更改群组路径、更改项目路径或更改分支名称。
如果您使用早于 17.12 的 Docker engine 版本,您还可能会收到 404 Not Found
或 Unknown Manifest
消息。更高版本的 Docker engine 使用 v2 API。
GitLab Container Registry 中的镜像也必须使用 Docker v2 API。 有关如何更新镜像的信息,请参阅 Docker 帮助。
清理策略不会删除任何标签
这背后可能有不同的原因:
-
在 13.6 及更早版本中,当您运行清理策略时,您可能希望它会删除标签,但事实并非如此。当清理策略被保存而不编辑 删除匹配的标签 字段中的值时,就会发生这种情况。该字段有一个灰色的
.*
值作为占位符。除非在字段中明确输入了.*
(或其他正则表达式模式),否则会提交一个nil
值,此值可防止保存的清理策略匹配任何标签。作为解决方法,请编辑清理策略。在 删除匹配的标签 字段中,输入.*
并保存,此值表示应删除所有标签。 -
如果您在自助管理实例上并且容器镜像库中有 1000 多个标签,您可能会遇到 Container Registry 令牌过期问题,并在日志中显示
error authorizing context: invalid token
。要解决此问题,有两种解决方法:
-
如果您使用的是 13.9 或更高版本,您可以为清理策略设置限制。这样可以及时限制清理执行,并避免过期令牌错误。
-
延长 Container Registry 身份验证令牌的到期延迟。默认为 5 分钟。您可以通过在 Rails 控制台中运行
ApplicationSetting.last.update(container_registry_token_expire_delay: <integer>)
来设置自定义值,其中<integer>
是所需的分钟数。请注意,通过扩展此值会增加撤销权限所需的时间。
-
如果以前的修复不起作用或者您使用的是早期版本,您可以生成要删除的标签列表,然后使用该列表删除标签。请按照下列步骤操作:
-
运行以下 shell 脚本。
for
循环之前的命令确保在启动循环时始终重新初始化list_o_tags.out
。运行此命令后,所有标签的名称都将在list_o_tags.out
文件中:# Get a list of all tags in a certain container repository while considering [pagination](../../../api/index.md#pagination) echo -n "" > list_o_tags.out; for i in {1..N}; do curl --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags?per_page=100&page=${i}" | jq '.[].name' | sed 's:^.\(.*\).$:\1:' >> list_o_tags.out; done
如果您有 Rails 控制台访问权限,则可以输入以下命令来检索受日期限制的标签列表:
output = File.open( "/tmp/list_o_tags.out","w" ) Project.find(<Project_id>).container_repositories.find(<container_repo_id>).tags.each do |tag| output << tag.name + "\n" if tag.created_at < 1.month.ago end;nil output.close
这组命令创建了一个
/tmp/list_o_tags.out
文件,其中列出了created_at
日期超过一个月的所有标签。 -
从
list_o_tags.out
文件中删除您想要保留的任何标签。以下是一些用于此的示例sed
命令。请注意,这些命令只是示例。您可以更改它们以适合您的需要:# Remove the `latest` tag from the file sed -i '/latest/d' list_o_tags.out # Remove the first N tags from the file sed -i '1,Nd' list_o_tags.out # Remove the tags starting with `Av` from the file sed -i '/^Av/d' list_o_tags.out # Remove the tags ending with `_v3` from the file sed -i '/_v3$/d' list_o_tags.out
如果您运行的是 macOS,则必须将
.back
添加到命令中。 例如:sed -i .bak '/latest/d' list_o_tags.out
-
仔细检查
list_o_tags.out
文件以确保它只包含您要删除的标签。 -
运行此 shell 脚本,删除
list_o_tags.out
文件中的标签:# loop over list_o_tags.out to delete a single tag at a time while read -r LINE || [[ -n $LINE ]]; do echo ${LINE}; curl --request DELETE --header 'PRIVATE-TOKEN: <PAT>' "https://gitlab.example.com/api/v4/projects/<Project_id>/registry/repositories/<container_repo_id>/tags/${LINE}"; sleep 0.1; echo; done < list_o_tags.out > delete.logs
作为 GitLab 服务器管理员进行故障排查
大多数情况下,对 GitLab Container Registry 进行故障排查,需要您以管理员角色登录到 GitLab 服务器。
阅读如何对 Container Registry 进行故障排查。
无法更改路径或传输项目
如果您尝试更改项目的路径或将项目转移到新的命名空间,您可能会收到以下错误之一:
- “Project cannot be transferred, because tags are present in its container registry.”
- “Namespace cannot be moved because at least one project has tags in container registry.”
当项目在 Container Registry 中有镜像时会出现此问题。 您必须先删除或移动这些镜像,然后才能更改路径或传输项目。
以下过程使用这些示例项目名称:
- 对于当前项目:
gitlab.example.com/org/build/sample_project/cr:v2.9.1
- 对于新项目:
gitlab.example.com/new_org/build/new_sample_project/cr:v2.9.1
使用您自己的 URL 完成以下步骤:
-
在您的计算机上下载 Docker 镜像:
docker login gitlab.example.com docker pull gitlab.example.com/org/build/sample_project/cr:v2.9.1
-
重命名镜像以匹配新项目名称:
docker tag gitlab.example.com/org/build/sample_project/cr:v2.9.1 gitlab.example.com/new_org/build/new_sample_project/cr:v2.9.1
- 使用 UI 或 API 删除两个项目中的镜像。镜像排队和删除时可能会有延迟。
- 通过转到 设置 > 通用 并展开 高级 来更改路径或传输项目。
-
恢复镜像:
docker push gitlab.example.com/new_org/build/new_sample_project/cr:v2.9.1