GitLab Container Registry

note如果您从 Docker Hub 拉取容器镜像,您还可以使用 GitLab Dependency Proxy 来避免遇到速率限制并加快流水线速度。

通过将 Docker Container Registry 集成到极狐GitLab 中,每个极狐GitLab 项目都可以拥有自己的空间来存储其 Docker 镜像。

您可以在 https://docs.docker.com/registry/introduction/ 阅读有关 Docker Registry 的更多信息。

本文档是用户指南。要了解如何为您的极狐GitLab 实例启用容器镜像库,请访问管理员文档

查看 Container Registry

您可以查看项目或群组的 Container Registry。

  1. 转到您的项目或群组。
  2. 转至 软件包与镜像库 > 容器镜像库

您可以在此页面上搜索、排序、过滤和删除容器。您可以通过从浏览器复制 URL 来共享过滤视图。

只有项目或群组的成员才能访问私有项目的 Container Registry。

如果项目是公开的,那么 Container Registry 也是公开的。

使用来自 Container Registry 的镜像

要下载并运行托管在 GitLab Container Registry 中的容器镜像:

  1. 将链接复制到您的容器镜像:
    • 转到您的项目或群组的 软件包与镜像库 > 容器镜像库 并找到您想要的镜像。
    • 在镜像名称旁边,单击 复制 按钮。

    Container Registry image URL

  2. 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:

  1. 使用 Container Registry 进行身份验证。

  2. 运行命令构建或推送。例如,要构建:

    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
note这个例子显式地调用了 docker pull。如果您更喜欢使用 image: 隐式拉取构建的镜像,并使用 Docker 或 Kubernetes executor,确保 pull_policy 设置为 always

使用 Container Registry 中的 Docker-in-Docker 镜像

要将您自己的 Docker 镜像用于 Docker-in-Docker,除了 Docker-in-Docker 部分中的步骤之外,还请按照以下步骤操作:

  1. 更新 imageservice 以指向您的镜像库。
  2. 添加服务别名。

下面是 .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 部分中的步骤之外,还请按照以下步骤操作:

  1. 更新 imageservice 以指向您的镜像库。
  2. 添加服务别名

下面是 .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 中删除镜像。

caution删除镜像是一种破坏性操作,无法撤消。要恢复已删除的镜像,您必须重建并重新上传它。
note管理员应该注意如何回收删除的镜像。

从极狐GitLab 中删除镜像

从极狐GitLab 中删除镜像:

  1. 导航到您的项目或群组的 软件包与镜像库 > 容器镜像库
  2. 容器镜像库 页面,您可以通过以下任一方式选择要删除的内容:

    • 通过单击红色的 Trash 图标删除整个仓库及其包含的所有标签。
    • 导航到仓库,并通过单击要删除的标签旁边的红色 Trash 图标来单独或批量删除标签。
  3. 在对话框中,单击 删除标签

使用 GitLab CI/CD 删除镜像

cautionGitLab CI/CD 不提供删除镜像的内置方法,但此示例使用名为 reg 的第三方工具与 GitLab Registry API 对话。您需对自己的操作负责。 有关此工具的帮助,请参阅 reg 的问题队列

以下示例定义了两个阶段:buildcleanbuild_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
note您可以从发布页面下载最新的 reg 版本,然后通过更改 delete_image 作业中定义的 REG_SHA256REG_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 中的所有标签并排除标签,直到只剩下要删除的标签为止。

清理策略根据标签名称搜索镜像。对完整路径的支持尚未实现,但允许您清理动态命名的标签。

清理策略:

  1. 在列表中收集给定仓库的所有标签。
  2. 从列表中排除名为 latest 的标签。
  3. 评估 name_regex(要过期的标签),从列表中排除不匹配的名称。
  4. 从列表中排除任何与 name_regex_keep 值匹配的标签(要保留的标签)。
  5. 排除任何没有 manifest 的标签(不是 UI 中选项的一部分)。
  6. created_date 对剩余标签进行排序。
  7. 根据 keep_n 值(要保留的标签数)从列表中排除 N 个标签。
  8. 从列表中排除比 older_than 值(过期间隔)更新的标签。
  9. 最后,将列表中剩余的标签从 Container Registry 中删除。
caution自助管理实例支持符合 Docker Registry HTTP API V2 规范的第三方容器镜像库。但是,该规范不包括标签删除操作。

创建清理策略

您可以在 API 或 UI 中创建清理策略。

要在 UI 中创建清理策略:

  1. 对于您的项目,转到 设置 > 软件包与镜像库
  2. 展开 清理镜像标签 部分。
  3. 填写字段。

    字段 描述
    切换 打开或关闭策略。
    运行清理 策略应该多久运行一次。
    保留最近的 总是为每个镜像保留多少标签。
    保留匹配标签 确定要保留哪些标签的正则表达式 pattern。latest 标签总是被保留。对于所有标签,使用 .*。请参阅其他 regex pattern 示例
    删除早于以下时间的标签 仅删除早于 X 天的标签。
    删除匹配的标签 确定要删除哪些标签的正则表达式 pattern。该值不能为空。对于所有标签,使用 .*。请参阅其他 regex 模式示例
  4. 点击 保存

根据您选择的时间间隔,策略将被安排运行。

note如果您编辑策略并再次单击 保存,则会重置间隔。

正则表达式 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)

或者,一旦限制被启用,它们在管理中心可用:

  1. 在顶部栏上,选择 菜单 > 管理员
  2. 进入 设置 > 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:

  1. 转到您项目的 设置 > 常规 页面。
  2. 展开可见性、项目功能、权限部分并禁用Container Registry
  3. 单击保存更改

软件包与镜像库 > 容器镜像库 条目从项目的侧边栏中删除。

更改 Container Registry 的可见性

引入于 14.2 版本。

默认情况下,每个有权访问项目的人都可以看到 Container Registry。 但是,您可以更改项目的 Container Registry 的可见性。

有关此设置授予用户的权限的更多详细信息,请参阅 Container Registry 可见性权限

  1. 转到您项目的 设置 > 通用 页面。
  2. 展开可见性、项目功能、权限部分。
  3. 容器镜像库 下,从下拉列表中选择一个选项:

    • 具有访问权限的任何人(默认):Container Registry 对所有有权访问项目的人可见。如果项目是公开的,那么 Container Registry 也是公开的。如果项目是内部的或私有的,那么 Container Registry 也是内部的或私有的。

    • 仅项目成员:Container Registry 仅对具有报告者角色或更高角色的项目成员可见。这类似于将 Container Registry 可见性设置为 具有访问权限的任何人 的私有项目的行为。

  4. 选择 保存修改

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 FoundUnknown 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> 是所需的分钟数。请注意,通过扩展此值会增加撤销权限所需的时间。

如果以前的修复不起作用或者您使用的是早期版本,您可以生成要删除的标签列表,然后使用该列表删除标签。请按照下列步骤操作:

  1. 运行以下 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 日期超过一个月的所有标签。

  2. 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
    
  3. 仔细检查 list_o_tags.out 文件以确保它只包含您要删除的标签。

  4. 运行此 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 完成以下步骤:

  1. 在您的计算机上下载 Docker 镜像:

    docker login gitlab.example.com
    docker pull gitlab.example.com/org/build/sample_project/cr:v2.9.1
    
  2. 重命名镜像以匹配新项目名称:

    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
    
  3. 使用 UI 或 API 删除两个项目中的镜像。镜像排队和删除时可能会有延迟。
  4. 通过转到 设置 > 通用 并展开 高级 来更改路径或传输项目。
  5. 恢复镜像:

    docker push gitlab.example.com/new_org/build/new_sample_project/cr:v2.9.1