GitLab Runner 制作 Docker 镜像的 5 种方案
参考示例
源码
理论执行效率
shell
> docker_sock
> docker_host
> using_docker_build
> using_kaniko
分支 | 关键流程 | 优点 |
---|---|---|
shell | 无需创建容器,直接使用宿主机的 docker 服务 | 可使用历史镜像、构建缓存 |
docker_sock | 使用 docker:cli 镜像 创建容器 时 挂载宿主机的 docker.sock ,直接利用宿主机的 docker.sock 服务 | 可使用历史镜像、构建缓存 |
docker_host | 使用 docker:cli 镜像 创建容器 后,使用网络与 docker 服务进行通信 | 可使用历史镜像、构建缓存 |
using_docker_build | 使用 docker:cli 镜像 创建容器 后,再使用 docker:dind 镜像创建 docker 服务 | 不可使用历史镜像、构建缓存 |
using_kaniko | 使用 gcr.io/kaniko-project/executor 镜像 创建容器,模拟 docker 功能 | 不可使用历史镜像、构建缓存 |
修改 GitLab Runner 运行时用户
- 根据需要进行调整
shell
# 查看当前runner用户
ps aux | grep gitlab-runner
# 删除gitlab-runner
sudo gitlab-runner uninstall
# 安装并设置--user(例如我想设置为root)
gitlab-runner install --working-directory /home/gitlab-runner --user root
# 重启gitlab-runner
sudo service gitlab-runner restart
# 再次执行会发现--user的用户名已经更换成root了
ps aux | grep gitlab-runner
方案 1:使用 Docker-in-Docker 构建 Docker 镜像
文档
- 极狐 GitLab:中文文档
介绍
在 Docker 中使用 Docker 镜像创建 Docker 容器,并在该容器内构建 Docker 镜像
- Docker 构建时的环境是一个独立的、隔离的 Docker 环境
- 需要 运行 GitLab 流水线,
- GitLab Runner 流水线 使用 Docker-in-Docker 执行时需要创建两个容器
- 使用
docker:cli
创建一个 Docker 客户端容器,也就是流水线执行时的容器- 在早期相关文档介绍时,使用
docker:latest
(最新版Docker命令行镜像)、docker:26.1.1
(指定版本的Docker命令行镜像)、26.1.1-alpine3.19
(指定版本的使用alpine
为基础镜像的Docker命令行镜像) - 在比较新的相关文档介绍时,使用
docker:cli
(最新版、最小化Docker命令行镜像)、docker:26.1.1-cli
(指定版本的、最小化Docker命令行镜像)、docker:26.1.1-cli-alpine3.19
(指定版本的、最小化使用alpine
为基础镜像的Docker命令行镜像)
- 在早期相关文档介绍时,使用
- 使用
docker:dind
创建一个 Docker 服务端容器,此容器需要使用 运行- 在流水线中,使用关键字 services 来创建流水线执行时所需的服务
- GitLab Runner Docker 执行器 配置,其他执行器配置雷同yaml
# 配置文件位置:/etc/gitlab-runner/config.toml [[runners]] name = "lighthouse-docker" url = "https://jihulab.com/" ...省略 executor = "docker" [runners.docker] # 此处配置 privileged = true,让流水线使用特权身份执行 privileged = true ...省略
- 使用
- 支持 GitLab Runner 执行器:
docker
、docker+machine
、kubernetes
等等 - 具体配置请参见 参考示例 的
using_docker_build
分支 - 由于每次执行时,都是创建一个新的 docker 服务,因此无法使用历史镜像,如果基础镜像很大,每次构建都会重新拉取,影响构建速度
方案 2:使用 kaniko 构建 Docker 镜像
文档
- 极狐 GitLab:中文文档
介绍
使用 gcr.io/kaniko-project/executor:debug
模拟 Docker 环境制作 Docker 镜像,无需特权身份运行
- Docker 构建时的环境是一个独立的、隔离的 Docker 环境
- 不需要 特权身份 运行 GitLab 流水线,不存在越权行为
- GitLab Runner 流水线 使用 kaniko 执行时只需要创建一个容器
- 支持 GitLab Runner 执行器:
docker
、docker+machine
、kubernetes
等等 gcr.io/kaniko-project/executor:debug
是最新版的镜像,推荐使用 具体版本(为了防止某天镜像进行不兼容更新造成异常)的kaniko
镜像, 如:gcr.io/kaniko-project/executor:v1.21.0-debug
,可访问 kaniko 仓库 仓库的 标签 来选择具体的版本- 由于国内可能无法访问
gcr.io
域名,推荐大家使用作者个人镜像 xuxiaoweicomcn/kaniko-project-executor- 镜像标签名与原始标签保持一致即可
- 使用 GitLab 流水线 每周自动同步一次,镜像内容未做任何修改
- 具体配置请参见 参考示例 的
using_kaniko
分支 - kaniko 无法使用历史镜像,如果基础镜像很大,每次构建都会重新拉取,影响构建速度
方案 3:使用 DOCKER_HOST
环境变量 指定现存的 Docker 服务 构建 Docker 镜像
文档
介绍
执行 Docker 命令 时,Docker 命令行工具 会 检查 环境变量 DOCKER_HOST
是否存在,如果存在时,Docker 命令行工具会与之通信, 用于完成 Docker 执行的命令
- Docker 构建时的环境是一个已经存在的环境,非独立环境
- 不需要 特权身份 运行 GitLab 流水线,不存在越权行为
- 环境变量
DOCKER_HOST
的示例:tcp://192.168.5.4:2375
(即:http)、tcp://192.168.5.4:2376
(即:https,需要配置证书才能使用) - 已安装的 Docker 服务,默认不开启远程调用的端口(即:默认不开启
2375
、2376
端口),如需开启,请参考下列配置:- 以下以 Docker 服务的宿主机的 IP 是
192.168.5.4
为例,Docker 服务仅开启 监听2375
、2376
端口,不监听其他 IP () - 编辑 Docker 服务shell
vim /lib/systemd/system/docker.service
- 默认 Docker 服务shell
[Unit] ... 省略 [Service] Type=notify ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock ... 省略 [Install] ... 省略
- 修改 Docker 服务shell
[Unit] ... 省略 [Service] Type=notify # 此处配置 Docker 监听的 端口 对应的 IP 是服务器的 内网IP,当且仅当使用 192.168.5.4:2375 才能与 Docker 进行远程通信 # 强烈不建议此处配置为 tcp://0.0.0.0:2375,是为了防止云服务器意外暴露 Docker 端口时,被其他人使用 公网IP 恶意访问,导致信息泄露 # 强烈不建议此处配置为 tcp://公网IP:2375,是为了防止云服务器意外暴露 Docker 端口时,被其他人使用 公网IP 恶意访问,导致信息泄露 # 如需监听公网 IP,请使用云服务安全组、服务器防火墙限制 IP 访问 Docker 端口,用于提高安全性 ExecStart=/usr/bin/dockerd -H tcp://192.168.5.4:2375 -H unix:///var/run/docker.sock ... 省略 [Install] ... 省略
- 以下以 Docker 服务的宿主机的 IP 是
- 支持 GitLab Runner 执行器:
docker
、docker+machine
、kubernetes
等等 - 具体配置请参见 参考示例 的
docker_host
分支 - 可以使用历史镜像,基础镜像只会拉取一次,可有效提高构建速度
方案 4:使用宿主机 docker.sock
提供 Docker 服务 构建 Docker 镜像
文档
介绍
执行 Docker 命令 时,Docker 命令行工具 会 检查 目录 /var/run/docker.sock
、/run/docker.sock
是否存在,如果存在时,Docker 命令行工具会与之通信,用于完成 Docker 执行的命令
- Docker 构建时的环境是一个已经存在的环境,非独立环境
- 不需要 特权身份 运行 GitLab 流水线,不存在越权行为
- 需要在 GitLab Runner 执行器所在的宿主机安装 Docker 服务,并保持 Docker 正常运行
- 需要在 GitLab Runner 执行器配置文件(夹)路径挂载
- GitLab Runner Docker 执行器 文件(夹)路径挂载 配置,其他执行器配置雷同yaml
# 配置文件位置:/etc/gitlab-runner/config.toml [[runners]] name = "lighthouse-docker" url = "https://jihulab.com/" ...省略 executor = "docker" [runners.docker] ...省略 volumes = ["/run/docker.sock:/run/docker.sock"] ...省略
- GitLab Runner Docker 执行器 文件(夹)路径挂载 配置,其他执行器配置雷同
- 支持 GitLab Runner 执行器:
docker
、docker+machine
、kubernetes
等等 - 具体配置请参见 参考示例 的
docker_sock
分支 - 可以使用历史镜像,基础镜像只会拉取一次,可有效提高构建速度
方案 5:使用 Shell 直接构建 Docker 镜像
直接使用 Shell 执行器构建 Docker 镜像,无需镜像
- Docker 构建时的环境是一个已经存在的环境,非独立环境,在 GitLab Runner 执行器宿主机上直接执行
- 需要在 GitLab Runner 执行器所在的宿主机安装 Docker 服务,并保持 Docker 正常运行
- 需要 GitLab Runner 运行时用户可正常执行 Docker 命令
- 支持 GitLab Runner 执行器:
shell
- 具体配置请参见 参考示例 的
shell
分支 - 可以使用历史镜像,基础镜像只会拉取一次,可有效提高构建速度