{{< details >}}

  • Tier: 基础版, 专业版, 旗舰版
  • Offering: JihuLab.com, 私有化部署

{{< /details >}}

你可以在专用 CI/CD 构建服务器或本地机器上托管的 Docker 容器中运行你的 CI/CD 作业。

要在 Docker 容器中运行 CI/CD 作业,你需要:

  1. 注册一个 runner 并配置它使用 Docker executor
  2. .gitlab-ci.yml 文件中指定你想要运行 CI/CD 作业的容器镜像。
  3. 可选。在容器中运行其他服务,例如 MySQL。通过在 .gitlab-ci.yml 文件中指定 services 来实现。

注册一个使用 Docker executor 的 runner

要在 Docker 中使用极狐GitLab Runner,你需要 注册一个 runner,使其使用 Docker executor。

下面的示例展示了如何设置一个临时模板来提供服务:

cat > /tmp/test-config.template.toml << EOF
[[runners]]
[runners.docker]
[[runners.docker.services]]
name = "postgres:latest"
[[runners.docker.services]]
name = "mysql:latest"
EOF

然后使用这个模板来注册 runner:

sudo gitlab-runner register \
  --url "https://gitlab.example.com/" \
  --token "$RUNNER_TOKEN" \
  --description "docker-ruby:2.6" \
  --executor "docker" \
  --template-config /tmp/test-config.template.toml \
  --docker-image ruby:3.3

注册的 runner 使用 ruby:2.6 Docker 镜像并运行两个服务,postgres:latestmysql:latest,两者都可以在构建过程中访问。

什么是镜像

image 关键字是 Docker executor 用来运行 CI/CD 作业的 Docker 镜像的名称。

默认情况下,executor 从 Docker Hub 拉取镜像。然而,你可以在 gitlab-runner/config.toml 文件中配置注册表位置。例如,你可以设置 Docker pull policy 来使用本地镜像。

镜像要求

用于运行 CI/CD 作业的任何镜像必须安装以下应用程序:

  1. shbash
  2. grep

.gitlab-ci.yml 文件中定义 image

你可以定义用于所有作业的镜像,以及你希望在运行时使用的服务列表:

default:
  image: ruby:2.6
  services:
    - postgres:11.7
  before_script:
    - bundle install

test:
  script:
    - bundle exec rake spec

镜像名称必须采用以下格式之一:

  1. image: <image-name> (与使用 <image-name>latest 标签相同)
  2. image: <image-name>:<tag>
  3. image: <image-name>@<digest>

扩展 Docker 配置选项

{{< history >}}

  • 在极狐GitLab和极狐GitLab Runner 9.4 中引入。

{{< /history >}}

你可以为 imageservices 条目使用字符串或映射:

  1. 字符串必须包含完整的镜像名称(包括注册表,如果你想从 Docker Hub 以外的注册表下载镜像)。
  2. 映射必须至少包含 name 选项,即与字符串设置使用的镜像名称相同。

例如,下面的两个定义是等价的:

  1. imageservices 的字符串:
  image: "registry.example.com/my/image:latest"

  services:
    - postgresql:14.3
    - redis:latest
  1. imageservices 的映射。image:name 是必需的:
  image:
    name: "registry.example.com/my/image:latest"

  services:
    - name: postgresql:14.3
    - name: redis:latest

脚本在哪里执行

当 CI 作业在 Docker 容器中运行时,before_scriptscriptafter_script 命令在 /builds/<project-path>/ 目录中运行。你的镜像可能定义了不同的默认 WORKDIR。要移动到你的 WORKDIR,请将 WORKDIR 保存为环境变量,以便在作业运行时在容器中引用它。

覆盖镜像的 entrypoint

{{< history >}}

  • 在极狐GitLab和极狐GitLab Runner 9.4 中引入。阅读更多关于 扩展配置选项

{{< /history >}}

在解释可用的 entrypoint 覆盖方法之前,让我们描述 runner 如何启动。它使用 Docker 镜像来为 CI/CD 作业使用的容器启动:

  1. runner 使用定义的 entrypoint 启动 Docker 容器。默认值来自 Dockerfile,可以在 .gitlab-ci.yml 文件中覆盖。
  2. runner 附加到正在运行的容器。
  3. runner 准备一个脚本(before_scriptscriptafter_script 的组合)。
  4. runner 将脚本发送到容器的 shell stdin 并接收输出。

要在 .gitlab-ci.yml 文件中覆盖 Docker 镜像的 entrypoint

  1. 对于 Docker 17.06 及更高版本,将 entrypoint 设置为空值。
  2. 对于 Docker 17.03 及更早版本,将 entrypoint 设置为 /bin/sh -c/bin/bash -c 或镜像中可用的等效 shell。

image:entrypoint 的语法类似于 Dockerfile ENTRYPOINT

假设你有一个带有 SQL 数据库的 super/sql:experimental 镜像。你想使用它作为你的作业的基础镜像,因为你想使用这个数据库二进制文件执行一些测试。还假设这个镜像配置了 /usr/bin/super-sql run 作为 entrypoint。当容器启动时,没有其他选项,它运行数据库的进程。runner 期望镜像没有 entrypoint 或 entrypoint 准备好启动 shell 命令。

使用扩展 Docker 配置选项,而不是:

  1. 基于 super/sql:experimental 创建你自己的镜像。
  2. ENTRYPOINT 设置为 shell。
  3. 在你的 CI 作业中使用新镜像。

现在你可以在 .gitlab-ci.yml 文件中定义 entrypoint

对于 Docker 17.06 及更高版本:

image:
  name: super/sql:experimental
  entrypoint: [""]

对于 Docker 17.03 及更早版本:

image:
  name: super/sql:experimental
  entrypoint: ["/bin/sh", "-c"]

config.toml 中定义镜像和服务

config.toml 文件中,你可以定义:

  1. [runners.docker] 部分,运行 CI/CD 作业使用的容器镜像
  2. [[runners.docker.services]] 部分,services 容器
[runners.docker]
  image = "ruby:latest"
  services = ["mysql:latest", "postgres:latest"]

以这种方式定义的镜像和服务被添加到该 runner 运行的所有作业中。

从私有容器注册表访问镜像

为了访问私有容器注册表,极狐GitLab Runner 进程可以使用:

  1. 静态定义的凭据。特定注册表的用户名和密码。
  2. 凭据存储
  3. 凭据助手

当你在同一极狐GitLab实例上使用 极狐GitLab Container Registry 时,极狐GitLab 为该注册表提供默认凭据。使用这些凭据,CI_JOB_TOKEN 用于身份验证。要使用作业令牌,启动作业的用户必须至少拥有托管私有镜像的项目的开发者角色。托管私有镜像的项目还必须允许其他项目使用作业令牌进行身份验证。默认情况下,此访问是禁用的。有关更多详细信息,请参见 CI/CD 作业令牌

要定义应该使用哪个选项,runner 进程按以下顺序读取配置:

  1. DOCKER_AUTH_CONFIG CI/CD 变量
  2. 在 runner 的 config.toml 文件中设置的 DOCKER_AUTH_CONFIG 环境变量。
  3. 运行进程的用户的 $HOME/.docker 目录中的 config.json 文件。如果提供了 --user 标志以非特权用户身份运行子进程,则使用主 runner 进程用户的主目录。

要求和限制

  1. 凭据存储凭据助手 需要将二进制文件添加到极狐GitLab Runner $PATH,并需要访问来执行此操作。因此,这些功能在实例 runner 或用户无法访问安装 runner 的环境的其他 runner 上不可用。

使用静态定义的凭据

你可以使用两种方法访问私有注册表。两者都需要设置 CI/CD 变量 DOCKER_AUTH_CONFIG,其中包含适当的身份验证信息。

  1. 每作业:要配置一个作业以访问私有注册表,请将 DOCKER_AUTH_CONFIG 添加为 CI/CD 变量
  2. 每 runner:要配置一个 runner,使其所有作业都可以访问私有注册表,请将 DOCKER_AUTH_CONFIG 添加为 runner 配置中的环境变量。

请参阅下面的每个示例。

确定你的 DOCKER_AUTH_CONFIG 数据

例如,假设你要使用 registry.example.com:5000/private/image:latest 镜像。此镜像是私有的,需要你登录私有容器注册表。

还假设这些是登录凭据:

Key Value
registry registry.example.com:5000
username my_username
password my_password

使用以下方法之一来确定 DOCKER_AUTH_CONFIG 的值:

  1. 在本地机器上进行 docker login
  docker login registry.example.com:5000 --username my_username --password my_password

然后复制 ~/.docker/config.json 的内容。

如果你不需要从计算机访问注册表,可以进行 docker logout

  docker logout registry.example.com:5000
  1. 在某些设置中,可能是 Docker 客户端使用可用的系统密钥存储来存储 docker login 的结果。在这种情况下,无法读取 ~/.docker/config.json,因此你必须准备 ${username}:${password} 的所需 base64 编码版本,并手动创建 Docker 配置 JSON。打开终端并执行以下命令:
  # 使用 printf(而不是 echo)可以防止在密码中编码换行。
  printf "my_username:my_password" | openssl base64 -A

  # 示例输出以供复制
  bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=

{{< alert type=”note” >}}

如果用户名包含诸如 @ 的特殊字符,则必须使用反斜杠(\)对其进行转义以防止身份验证问题。

{{< /alert >}}

按如下方式创建 Docker JSON 配置内容:

  {
      "auths": {
          "registry.example.com:5000": {
              "auth": "(Base64 content from above)"
          }
      }
  }

配置作业

要配置一个作业以访问 registry.example.com:5000,请按照以下步骤操作:

  1. 创建一个 CI/CD 变量 DOCKER_AUTH_CONFIG,其值为 Docker 配置文件的内容:

    {
        "auths": {
            "registry.example.com:5000": {
                "auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
            }
        }
    }
    
  2. 现在你可以在 .gitlab-ci.yml 文件中使用从 registry.example.com:5000 定义的 imageservices 的任何私有镜像:

    image: registry.example.com:5000/namespace/image:tag
    

    在上面的示例中,极狐GitLab Runner 会在 registry.example.com:5000 查找镜像 namespace/image:tag

你可以为任意数量的注册表添加配置,将更多注册表添加到 "auths" 哈希中,如上所述。

runner 匹配 DOCKER_AUTH_CONFIG 时,所有地方都需要完整的 hostname:port 组合。例如,如果在 .gitlab-ci.yml 文件中指定了 registry.example.com:5000/namespace/image:tag,那么 DOCKER_AUTH_CONFIG 也必须指定 registry.example.com:5000。仅指定 registry.example.com 是不起作用的。

配置 runner

如果你有许多流水线访问相同的注册表,你应该在 runner 级别设置注册表访问。这样,流水线作者只需在适当的 runner 上运行作业即可访问私有注册表。这也有助于简化注册表更改和凭据轮换。

这意味着该 runner 上的任何作业都可以访问注册表,甚至跨项目。如果你需要控制对注册表的访问,你需要确保控制对 runner 的访问。

要向 runner 添加 DOCKER_AUTH_CONFIG

  1. 按如下方式修改 runner 的 config.toml 文件:

    [[runners]]
      environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
    
    • DOCKER_AUTH_CONFIG 数据中包含的双引号必须用反斜杠转义。这可以防止它们被解释为 TOML。
    • environment 选项是一个列表。你的 runner 可能有现有条目,你应该将此添加到列表中,而不是替换它。
  2. 重启 runner 服务。

使用凭据存储

要配置凭据存储:

  1. 要使用凭据存储,你需要一个外部助手程序来与特定的钥匙串或外部存储进行交互。确保助手程序在极狐GitLab Runner 的 $PATH 中可用。

  2. 使极狐GitLab Runner 使用它。你可以通过以下选项之一来实现:

    • 创建一个 CI/CD 变量 DOCKER_AUTH_CONFIG,其值为 Docker 配置文件的内容:

        {
          "credsStore": "osxkeychain"
        }
      
    • 或者,如果你运行的是私有化部署 runner,请将上述 JSON 添加到 ${GITLAB_RUNNER_HOME}/.docker/config.json。极狐GitLab Runner 读取此配置文件并使用所需的助手为此特定存储库。

credsStore 用于访问 所有 注册表。如果你同时使用私有注册表的镜像和 Docker Hub 的公共镜像,那么从 Docker Hub 拉取会失败。Docker 守护进程尝试为 所有 注册表使用相同的凭据。

使用凭据助手

例如,假设你要使用 <aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest 镜像。此镜像是私有的,需要你登录私有容器注册表。

要为 <aws_account_id>.dkr.ecr.<region>.amazonaws.com 配置访问,请按照以下步骤操作:

  1. 确保 docker-credential-ecr-login 在极狐GitLab Runner 的 $PATH 中可用。
  2. 有任何以下 AWS 凭据设置。确保极狐GitLab Runner 可以访问凭据。
  3. 使极狐GitLab Runner 使用它。你可以通过以下选项之一来实现:

    • 创建一个 CI/CD 变量 DOCKER_AUTH_CONFIG,其值为 Docker 配置文件的内容:

      {
        "credHelpers": {
          "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login"
        }
      }
      

      这将配置 Docker 为特定注册表使用凭据助手。

      或者,你可以将 Docker 配置为为所有 Amazon Elastic Container Registry (ECR) 注册表使用凭据助手:

      {
        "credsStore": "ecr-login"
      }
      

      {{< alert type=”note” >}}

      如果你使用 {"credsStore": "ecr-login"},请在 AWS 共享配置文件 (~/.aws/config) 中显式设置区域。当 ECR 凭据助手检索授权令牌时,必须指定区域。

      {{< /alert >}}

    • 或者,如果你运行的是私有化部署 runner,请将之前的 JSON 添加到 ${GITLAB_RUNNER_HOME}/.docker/config.json。极狐GitLab Runner 读取此配置文件并为此特定存储库使用所需的助手。

  4. 现在你可以在 .gitlab-ci.yml 文件中使用从 <aws_account_id>.dkr.ecr.<region>.amazonaws.com 定义的 image 和/或 services 的任何私有镜像:

    image: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest
    

    在示例中,极狐GitLab Runner 会在 <aws_account_id>.dkr.ecr.<region>.amazonaws.com 查找镜像 private/image:latest

你可以为任意数量的注册表添加配置,将更多注册表添加到 "credHelpers" 哈希中。

使用校验和保持镜像安全

在你的 .gitlab-ci.yml 文件中的作业定义中使用镜像校验和来验证镜像的完整性。失败的镜像完整性验证会阻止你使用修改过的容器。

要使用镜像校验和,你必须在末尾附加校验和:

image: ruby:2.6.8@sha256:d1dbaf9665fe8b2175198e49438092fdbcf4d8934200942b94425301b17853c7

要获取镜像校验和,请在镜像 TAG 选项卡上查看 DIGEST 列。

你也可以使用 docker images --digests 命令获取你系统上任何镜像的校验和:

❯ docker images --digests
REPOSITORY                                                        TAG       DIGEST                                                                    (...)
gitlab/gitlab-ee                                                  latest    sha256:723aa6edd8f122d50cae490b1743a616d54d4a910db892314d68470cc39dfb24   (...)
gitlab/gitlab-runner                                              latest    sha256:4a18a80f5be5df44cb7575f6b89d1fdda343297c6fd666c015c0e778b276e726   (...)

创建自定义极狐GitLab Runner Docker 镜像

你可以创建一个自定义极狐GitLab Runner Docker 镜像来打包 AWS CLI 和 Amazon ECR 凭据助手。此设置促进与 AWS 服务的安全和简化交互,特别是对于容器化应用程序。例如,使用此设置来管理、部署和更新 Amazon ECR 上的 Docker 镜像。此设置有助于避免耗时、容易出错的配置和手动凭据管理。

  1. 使用 AWS 认证极狐GitLab
  2. 创建一个 Dockerfile,包含以下内容:

    # 控制包版本
    ARG GITLAB_RUNNER_VERSION=v17.3.0
    ARG AWS_CLI_VERSION=2.17.36
    
    # AWS CLI 和 Amazon ECR 凭据助手
    FROM amazonlinux as aws-tools
    RUN set -e \
        && yum update -y \
        && yum install -y --allowerasing git make gcc curl unzip \
        && curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" --output "awscliv2.zip" \
        && unzip awscliv2.zip && ./aws/install -i /usr/local/bin \
        && yum clean all
    
    # 下载并安装 ECR 凭据助手
    RUN curl --location --output  /usr/local/bin/docker-credential-ecr-login "https://github.com/awslabs/amazon-ecr-credential-helper/releases/latest/download/docker-credential-ecr-login-linux-amd64"
    RUN chmod +x /usr/local/bin/docker-credential-ecr-login
    
    # 配置 ECR 凭据助手
    RUN mkdir -p /root/.docker
    RUN echo '{ "credsStore": "ecr-login" }' > /root/.docker/config.json
    
    # 基于极狐GitLab Runner 的最终镜像
    FROM gitlab/gitlab-runner:${GITLAB_RUNNER_VERSION}
    
    # 安装必要的包
    RUN apt-get update \
        && apt-get install -y --no-install-recommends jq procps curl unzip groff libgcrypt20 tar gzip less openssh-client \
        && apt-get clean && rm -rf /var/lib/apt/lists/*
    
    # 复制 AWS CLI 和 Amazon ECR 凭据助手二进制文件
    COPY --from=aws-tools /usr/local/bin/ /usr/local/bin/
    
    # 复制 ECR 凭据助手配置
    COPY --from=aws-tools /root/.docker/config.json /root/.docker/config.json
    
  3. 要在 .gitlab-ci.yml 中构建自定义极狐GitLab Runner Docker 镜像,请包含以下示例:

    variables:
      DOCKER_DRIVER: overlay2
      IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
      GITLAB_RUNNER_VERSION: v17.3.0
      AWS_CLI_VERSION: 2.17.36
    
    stages:
      - build
    
    build-image:
      stage: build
      script:
        - echo "Logging into 极狐GitLab container registry..."
        - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
        - echo "Building Docker image..."
        - docker build --build-arg GITLAB_RUNNER_VERSION=${GITLAB_RUNNER_VERSION} --build-arg AWS_CLI_VERSION=${AWS_CLI_VERSION} -t ${IMAGE_NAME} .
        - echo "Pushing Docker image to 极狐GitLab container registry..."
        - docker push ${IMAGE_NAME}
      rules:
        - changes:
            - Dockerfile
    
  4. 注册 runner