- 注册一个使用 Docker executor 的 runner
- 什么是镜像
- 在
.gitlab-ci.yml
文件中定义image
- 扩展的 Docker 配置选项
- 脚本在哪里执行
- 在
config.toml
中定义镜像和服务 - 从私有 Container Registry 访问镜像
在 Docker 容器中运行 CI/CD 作业
您可以在单独的、隔离的 Docker 容器中运行 CI/CD 作业。
如果您在本地机器上运行 Docker,您可以在容器中运行测试,而不是在专用 CI/CD 服务器上进行测试。
要在 Docker 容器中运行 CI/CD 作业,您需要:
- 注册一个 runner,让所有作业都在 Docker 容器中运行。在注册期间选择 Docker executor。
- 指定在哪个容器中运行作业。在您的
.gitlab-ci.yml
文件中指定一个镜像。 - 可选。在容器中运行其他服务,如 MySQL。在您的
.gitlab-ci.yml
文件中指定 services。
注册一个使用 Docker executor 的 runner
要将 GitLab Runner 与 Docker 一起使用,您需要注册一个使用 Docker executor 的 runner。
此示例显示如何设置临时模板以提供 services:
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/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--description "docker-ruby:2.6" \
--executor "docker" \
--template-config /tmp/test-config.template.toml \
--docker-image ruby:2.6
注册的 runner 使用 ruby:2.6
Docker 镜像并运行两个服务,postgres:latest
和 mysql:latest
,这两个服务都可以在构建过程中访问。
什么是镜像
image
关键字是 Docker executor 用来运行 CI/CD 作业的 Docker 镜像的名称。
默认情况下,executor 从 Docker Hub 拉取镜像。
但是,您可以在 gitlab-runner/config.toml
文件中配置镜像库位置。
比如你可以设置 Docker 拉取策略,使用本地镜像。
有关镜像和 Docker Hub 的更多信息,请参阅 Docker Fundamentals。
在 .gitlab-ci.yml
文件中定义 image
您可以定义用于所有作业的镜像,以及要在运行时使用的 services 列表:
default:
image: ruby:2.6
services:
- postgres:11.7
before_script:
- bundle install
test:
script:
- bundle exec rake spec
镜像名称必须采用以下格式之一:
-
image: <image-name>
(与使用带有latest
标签的<image-name>
相同) image: <image-name>:<tag>
image: <image-name>@<digest>
扩展的 Docker 配置选项
您可以为 image
或 services
条目使用字符串或映射:
- 字符串必须包含完整镜像名称(如果要从 Docker Hub 以外的镜像库下载镜像,则包括镜像库)。
- 映射必须至少包含
name
选项,它与用于字符串设置的镜像名称相同。
例如,以下两个定义是等价的:
-
image
和services
的字符串:image: "registry.example.com/my/image:latest" services: - postgresql:14.3 - redis:latest
-
image
和services
的映射。image:name
是必需的:image: name: "registry.example.com/my/image:latest" services: - name: postgresql:14.3 - name: redis:latest
脚本在哪里执行
当 CI 作业在 Docker 容器中运行时,before_script
、script
和 after_script
命令在 /builds/<project-path>/
目录中运行。 您的镜像可能定义了不同的默认 WORKDIR
。要移动到您的 WORKDIR
,请将 WORKDIR
保存为环境变量,以便您可以在作业运行时在容器中引用它。
覆盖镜像的 entrypoint
在解释可用的 entrypoint 覆盖方法之前,让我们描述一下 runner 如何启动。它为 CI/CD 作业中使用的容器使用 Docker 镜像:
- runner 使用定义的 entrypoint 启动一个 Docker 容器。
Dockerfile
中的默认值可能会在.gitlab-ci.yml
文件中被覆盖。 - runner 将自己附加到正在运行的容器上。
- runner 准备一个脚本(
before_script
,script
和after_script
的组合)。 - runner 将脚本发送到容器的 shell
stdin
并接收输出。
要覆盖 Docker 镜像的 entrypoint,请在 .gitlab-ci.yml
文件中定义一个空的 entrypoint
,这样 runner 就不会启动无用的 shell 层。但是,这不适用于所有 Docker 版本。
- 对于 Docker 17.06 及更高版本,
entrypoint
可以设置为空值。 - 对于 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 配置选项,而不是:
- 基于
super/sql:experimental
创建自己的镜像。 - 将
ENTRYPOINT
设置为 shell。 - 在 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
中定义镜像和服务
寻找 [runners.docker]
部分:
[runners.docker]
image = "ruby:latest"
services = ["mysql:latest", "postgres:latest"]
以这种方式定义的镜像和服务将添加到该 runner 运行的所有作业中。
从私有 Container Registry 访问镜像
要访问私有容器镜像库,GitLab Runner 进程可以使用:
- 静态定义的凭据。也就是说,特定镜像库的用户名和密码。
- 凭据存储。有关更多信息,请参阅相关 Docker 文档。
-
Credential Helpers。有关更多信息,请参阅相关 Docker 文档。 要定义应使用哪个选项,runner 进程按以下顺序读取配置:
- 一个
DOCKER_AUTH_CONFIG
CI/CD 变量。 - 在 runner 的
config.toml
文件中设置的DOCKER_AUTH_CONFIG
环境变量。 - 运行进程的用户的
$HOME/.docker
目录中的config.json
文件。如果提供了--user
标志来以非特权用户身份运行子进程,则使用主运行进程用户的主目录。
要求和限制
- 适用于 GitLab Runner 13.1 及更高版本中的 Kubernetes executor。
-
凭据存储 和 Credential Helpers 需要将二进制文件添加到 GitLab Runner
$PATH
,并且需要访问权限才能这样做。因此,这些功能在共享 runner,或用户无权访问安装 runner 的环境的任何其他 runner 上不可用。
使用静态定义的凭据
您可以采用两种方法来访问私有镜像库。两者都需要使用适当的身份验证信息设置 CI/CD 变量 DOCKER_AUTH_CONFIG
。
- Per-job:要配置一个作业以访问私有镜像库,请将
DOCKER_AUTH_CONFIG
添加为 CI/CD 变量。 - Per-runner:要配置 runner 使其所有作业都可以访问私有镜像库,请在 runner 的配置中添加
DOCKER_AUTH_CONFIG
作为环境变量。
有关每个示例,请参见下文。
确定您的 DOCKER_AUTH_CONFIG
数据
例如,假设您要使用 registry.example.com:5000/private/image:latest
镜像。此镜像是私有的,需要您登录到私有容器镜像库。
我们还假设以下登录凭据:
键 | 值 |
---|---|
registry | registry.example.com:5000
|
username | my_username
|
password | my_password
|
使用以下方法之一来确定 DOCKER_AUTH_CONFIG
的值:
-
在本地机器上执行
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
-
在某些设置中,Docker 客户端可能使用可用的系统密钥存储来存储
docker login
的结果。在这种情况下,无法读取~/.docker/config.json
,因此您必须准备所需的 base64 编码版本的${username}:${password}
并手动创建 Docker 配置 JSON。 打开终端并执行以下命令:# The use of printf (as opposed to echo) prevents encoding a newline in the password. printf "my_username:my_password" | openssl base64 -A # Example output to copy bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=
创建 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="
}
}
}
-
您现在可以使用您的
.gitlab-ci.yml
文件中的image
或services
中定义的registry.example.com:5000
中的任何私有镜像:image: registry.example.com:5000/namespace/image:tag
在上面的示例中,GitLab Runner 在
registry.example.com:5000
中查找镜像namespace/image:tag
。
您可以根据需要为任意数量的镜像库添加配置,如上所述将更多镜像库添加到 "auths"
哈希。
Runner 在任何地方都需要完整的 hostname:port
组合以匹配 DOCKER_AUTH_CONFIG
。例如,在 .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 的访问。
要将 DOCKER_AUTH_CONFIG
添加到 runner:
-
修改 runner 的
config.toml
文件如下:[[runners]] environment = ["DOCKER_AUTH_CONFIG={\"auths\":{\"registry.example.com:5000\":{\"auth\":\"bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ=\"}}}"]
-
DOCKER_AUTH_CONFIG
数据中包含的双引号必须用反斜杠转义。这可以防止它们被解释为 TOML。 -
environment
选项是一个列表。您的 runner 可能有现有条目,您应该将其添加到列表中,而不是替换它。
-
-
重新启动 runner 服务。
使用凭证存储
要配置凭据存储:
-
要使用凭据存储,您需要一个外部帮助程序来与特定的钥匙串或外部存储进行交互。确保帮助程序在 GitLab Runner
$PATH
中可用。 -
让 GitLab Runner 使用它。有两种方法可以实现:
-
创建一个 CI/CD 变量
DOCKER_AUTH_CONFIG
,以 Docker 配置文件的内容为值:{ "credsStore": "osxkeychain" }
-
或者,如果您正在运行私有化部署的 runner,请将上述 JSON 添加到
${GITLAB_RUNNER_HOME}/.docker/config.json
。GitLab Runner 读取此配置文件并使用此特定仓库所需的 helper。
-
credsStore
用于访问 所有 镜像库。
如果您同时使用来自私有镜像库的镜像和来自 Docker Hub 的公共镜像,则从 Docker Hub 拉取将失败。Docker 守护进程尝试对所有镜像库使用相同的凭据。
使用 Credential Helpers
引入于 GitLab Runner 12.0。
例如,假设您要使用 <aws_account_id>.dkr.ecr.<region>.amazonaws.com/private/image:latest
镜像。此镜像是私有的,需要您登录私有容器镜像库。
要为 <aws_account_id>.dkr.ecr.<region>.amazonaws.com
配置访问权限,请按照以下步骤操作:
- 确保
docker-credential-ecr-login
在极狐GitLab Runner$PATH
中可用。 - 有以下任何 AWS 凭证设置。确保 GitLab Runner 可以访问凭据。
-
让 GitLab Runner 使用它有两种方法:
-
创建一个 CI/CD 变量
DOCKER_AUTH_CONFIG
,以 Docker 配置文件的内容为值:{ "credHelpers": { "<aws_account_id>.dkr.ecr.<region>.amazonaws.com": "ecr-login" } }
这会将 Docker 配置为对特定镜像库使用 Credential Helper。
相反,您可以将 Docker 配置为对所有 Amazon Elastic Container Registry (ECR) 镜像库使用 Credential Helper:
{ "credsStore": "ecr-login" }
-
或者,如果您正在运行私有化部署的 runner,请将之前的 JSON 添加到
${GITLAB_RUNNER_HOME}/.docker/config.json
。GitLab Runner 读取此配置文件并使用此特定仓库所需的 helper。
-
-
您现在可以使用来自
<aws_account_id>.dkr.ecr.<region>.amazonaws.com
的任何私有镜像,该镜像在.gitlab-ci.yml
文件中的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
列。
例如,查看 Ruby 镜像。
校验和是一个随机字符串,如 6155f0235e95
。
您还可以使用命令 docker images --digests
获取系统上任何镜像的校验和:
❯ docker images --digests
REPOSITORY TAG DIGEST (...)
gitlab/gitlab-ee latest sha256:723aa6edd8f122d50cae490b1743a616d54d4a910db892314d68470cc39dfb24 (...)
gitlab/gitlab-runner latest sha256:4a18a80f5be5df44cb7575f6b89d1fdda343297c6fd666c015c0e778b276e726 (...)