GitLab CI + Kaniko + 阿里云 ACR:实现无特权容器的镜像安全构建
在云原生环境(尤其是 Kubernetes 上的 GitLab Runner)中,传统的 Docker-in-Docker (dind) 模式因为需要特权模式(Privileged mode)运行,带来了极大的安全隐患。Kaniko 作为谷歌开源的工具,无需依赖 Docker Daemon 即可在容器内完成镜像构建,已成为目前 CI/CD 流水线中最推荐的镜像构建方案。
本文将详细介绍如何在 GitLab CI 中配置 Kaniko,并将其稳定地推送到阿里云容器镜像服务(ACR)。
一、 核心逻辑:Kaniko 如何进行身份验证?
Kaniko 不像 Docker 客户端可以通过 docker login 交互式登录。它在运行时会读取 /kaniko/.docker/config.json 文件来获取镜像仓库的认证凭据。因此,在 GitLab CI 流水线中,我们的核心任务是:动态生成这个包含阿里云 ACR 凭据的配置文件。
二、 准备工作:设置 GitLab 环境变量
为了安全起见,绝对不要将账号密码明文写在代码库中。请在 GitLab 项目的 Settings -> CI/CD -> Variables 中添加以下变量:
ACR_REGISTRY:阿里云 ACR 实例地址(如registry.cn-hangzhou.aliyuncs.com)。ACR_USER:阿里云 ACR 访问账号(通常是邮箱或子账号)。ACR_PASSWORD:阿里云 ACR 访问令牌(注意:是访问凭证,而非阿里云登录密码)。
三、 编写 .gitlab-ci.yml
以下是一个完整的配置示例,涵盖了目录创建、凭据写入、构建参数传递等细节。
stages:
- build
image-build-job:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug # 建议使用 debug 版本,内置了 shell
entrypoint: [""]
script:
# 1. 准备 Kaniko 的认证配置目录
- mkdir -p /kaniko/.docker
# 2. 将阿里云凭据写入 config.json
# 使用 base64 编码 user:password 格式
- echo "{\"auths\":{\"$ACR_REGISTRY\":{\"auth\":\"$(echo -n $ACR_USER:$ACR_PASSWORD | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
# 3. 执行 Kaniko 构建
# --context: 项目根目录
# --dockerfile: 指定 Dockerfile 路径
# --destination: 目标镜像全路径
# --cache: 开启构建缓存,极大提升二次构建速度
- /kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${ACR_REGISTRY}/your-namespace/your-repo:${CI_COMMIT_SHORT_SHA}"
--destination "${ACR_REGISTRY}/your-namespace/your-repo:latest"
--cache=true
--cache-repo="${ACR_REGISTRY}/your-namespace/cache"
only:
- main
四、 关键细节与进阶配置
1. 证书配置(Certificate Configuration)
如果你的阿里云 ACR 使用的是自签名证书或者企业内部的 CA 证书,Kaniko 会报错 x509: certificate signed by unknown authority。
解决方案:
在 GitLab CI 变量中定义一个 CA_CERT,然后在脚本中将其写入 Kaniko 的证书信任列表:
before_script:
- echo "$CA_CERT" > /kaniko/ssl/certs/additional-ca.crt
注意:Kaniko 的证书默认存放路径为 /kaniko/ssl/certs/。
2. 构建参数(Build Args)
如果 Dockerfile 中定义了 ARG,可以通过 --build-arg 传递变量:
- /kaniko/executor --build-arg VERSION=${CI_COMMIT_TAG} ...
3. 环境变量传递的坑
在生成 config.json 时,务必注意 base64 编码后的换行符问题。使用 tr -d '\n' 移除换行符是非常关键的,否则 Kaniko 无法解析损坏的 JSON 文件,导致认证失败。
五、 为什么选择 Kaniko 而非 Docker?
- 安全性:无需开启 GitLab Runner 的特权模式,降低宿主机被容器逃逸攻击的风险。
- 兼容性:在标准的 Kubernetes 集群中运行更顺滑,不需要挂载
/var/run/docker.sock。 - 性能:Kaniko 专门优化的缓存机制(
--cache)可以将构建层推送到远端仓库,在多节点流水线中也能共享缓存。
总结
通过 GitLab CI 环境变量配合 Kaniko 的 config.json 自动生成,我们可以构建一套高效且安全的镜像发布流水线。这种方案不仅适用于阿里云 ACR,也可以稍作修改后推广到腾讯云 TCR、华为云 SWR 或自建的 Harbor 仓库中。