最后更新于

在 PVE 中配置基于 Docker 的 GitLab Runner


环境准备

为了更好的隔离性,我在 PVE 中创建了一个新的 LXC 容器专门运行 GitLab Runner。这里使用了一个预装 Docker 的 LXC 模板,创建完成后把容器重命名为 gitlab-runner-1

Terminal window
pct set <VMID> --hostname gitlab-runner-1

GitLab Runner 配置

1. 注册 Runner

进入 https://yourgitlabhost/admin/runners , 点击 “New instance runner”

  • 标签随意,比如 linux, shared
  • 如果希望这个runner 可以被所有gitlab job 使用,勾选“Run untagged jobs”
  • 点击 Create runner

之后会进入一个注册 runner 页面

  1. 点击1 复制脚本进入lxc 安装gitlab runner
  2. 安装完成1之后,复制2的命令注册服务

2. 选择 Executor 类型

在注册过程中需要选择 executor 类型。这里我选择了 docker而不是默认的shell,因为它可以确保每次构建环境的独立性,而且部署也比较方便。反过来如果是shell就不能用pipeline里面的image 字段,而且需要确保script里面的调用命令都在机器上安装过,太麻烦了。GitLab Runner 支持的 executor 的详细说明可以查看官方文档

Docker 构建方案对比

在 Docker 环境中构建 Docker 镜像时,GitLab 提供了几种方案:

名称说明安全性方便程度性能已知问题
Docker-in-Docker在容器内运行完整的 Docker 环境,通过 TCP 通信高(完全隔离)中等(需要配置特权模式和证书)低(需要额外的 Docker daemon)已知问题
Docker socket binding直接使用宿主机的 Docker daemon低(可以访问宿主机 Docker)高(只需挂载 socket)高(直接使用宿主机资源)已知问题
Daemon-less 方案 (Kaniko/Buildah)不需要 Docker daemon 的容器构建工具高(无需特权)中等(需要配置凭证和缓存)中等(构建性能取决于配置)-

方案选择说明

最终我选择了 Docker socket binding 方案,主要基于以下考虑:

  1. 代码可信度:GitLab 仓库中的代码都是自己信任且熟悉的,运行恶意容器的风险较低
  2. 环境隔离:Runner 本身运行在无特权的 LXC 容器中,提供了额外的安全层面

3. Runner 配置

Runner 的完整配置说明可以参考官方文档,Docker 相关的具体配置在这里

配置文件示例

配置文件位置:/etc/gitlab-runner/config.toml

concurrent = 1
check_interval = 0
connection_max_age = "15m0s"
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "lxc docker"
url = "https://yourgitlaburl/"
id = 11
token = "yoyrgitlabtoken"
token_obtained_at = 2024-11-25T13:57:14Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
image = "docker:24.0.5"
privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache","/var/run/docker.sock:/var/run/docker.sock"]
shm_size = 0
network_mtu = 0

主要修改:

  • volumes 增加了 /var/run/docker.sock

修改完成后,重启 Runner:

Terminal window
sudo gitlab-runner restart

4. CI/CD 配置

Docker 认证配置

GitLab 提供了三种认证方式,最简单的是使用环境变量:

  • $DOCKER_REGISTRY_PASS:Docker 密码
  • $DOCKER_REGISTRY:Docker 仓库
  • $DOCKER_REGISTRY_USER:Docker 账号

CI/CD 配置示例

variables:
# GitLab 容器仓库的地址
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
stages:
- build
build_image:
image: docker:latest # 只在这个任务中使用 docker image
stage: build
script:
- docker info # 测试 docker 连接
- echo "Testing Docker build..."
- echo "CI_REGISTRY=$CI_REGISTRY"
- echo "CI_REGISTRY_IMAGE=$CI_REGISTRY_IMAGE"
- echo "CI_COMMIT_SHA=$CI_COMMIT_SHA"
- echo "IMAGE_TAG=$IMAGE_TAG"
# 登录到 GitLab 容器仓库
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" "$CI_REGISTRY" --password-stdin
# 使用缓存和多个标签来优化构建过程
- >-
docker build
--cache-from "$CI_REGISTRY_IMAGE:latest"
--build-arg BUILDKIT_INLINE_CACHE=1
-t "$IMAGE_TAG"
-t "$CI_REGISTRY_IMAGE:latest"
.
# 推送镜像
- docker push "$IMAGE_TAG"
- docker push "$CI_REGISTRY_IMAGE:latest"
- echo "Docker build and push successful!"
only:
- main

后续

  • 增加定期清理硬盘的任务。docker 构建出来的image在runner上面并不会自动删除,可以增加一个定期删除docker image的脚本,具体可以参考这里