{{< details >}}

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

{{< /details >}}

kaniko 是一个用于在容器或 Kubernetes 集群中从 Dockerfile 构建容器镜像的工具。

kaniko 解决了使用 Docker-in-Docker 构建 方法的两个问题:

  1. Docker-in-Docker 需要特权模式才能运行,这存在重大安全隐患。
  2. Docker-in-Docker 通常会导致性能下降,可能会非常慢。

先决条件

要在极狐GitLab 中使用 kaniko,需要一个具有以下执行器之一的 runner

  1. Kubernetes
  2. Docker
  3. Docker Machine

使用 kaniko 构建 Docker 镜像

在使用 kaniko 和极狐GitLab CI/CD 构建镜像时,你应该注意一些重要细节:

  1. 推荐使用 kaniko 调试镜像 (gcr.io/kaniko-project/executor:debug),因为它具有 shell,而使用极狐GitLab CI/CD 需要 shell。
  2. 需要 覆盖 entrypoint,否则构建脚本不会运行。

在以下示例中,使用 kaniko 来:

  1. 构建一个 Docker 镜像。
  2. 然后将其推送到 极狐GitLab 容器注册表

该作业仅在推送标签时运行。在 /kaniko/.docker 下创建一个 config.json 文件,其中包含从极狐GitLab CI/CD 提供的 预定义 CI/CD 变量 中获取的极狐GitLab 容器注册表凭据。这些凭据会被 Kaniko 工具自动读取。

在最后一步中,kaniko 使用项目根目录下的 Dockerfile 构建 Docker 镜像,并将其推送到项目的容器注册表,同时用 Git 标签标记它:

build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.23.2-debug
    entrypoint: [""]
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
  rules:
    - if: $CI_COMMIT_TAG

如果你在 Dependency Proxy 中进行身份验证,则必须将用于身份验证的相应 CI/CD 变量添加到 config.json 文件中:

- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"},\"$(echo -n $CI_DEPENDENCY_PROXY_SERVER | awk -F[:] '{print $1}')\":{\"auth\":\"$(printf "%s:%s" ${CI_DEPENDENCY_PROXY_USER} "${CI_DEPENDENCY_PROXY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json

此命令会去除 CI_DEPENDENCY_PROXY_SERVER 中的端口,例如 :443,因此在引用镜像时不必包括它。

在代理后使用 kaniko 构建镜像

如果你在 http(s) 代理后使用自定义极狐GitLab Runner,需要相应地设置 kaniko。这意味着:

  1. http_proxy 环境变量作为构建参数传递,以便 Dockerfile 指令在构建镜像时可以使用代理。

可以如下扩展前面的示例:

build:
  stage: build
  variables:
    http_proxy: <your-proxy>
    https_proxy: <your-proxy>
    no_proxy: <your-no-proxy>
  image:
    name: gcr.io/kaniko-project/executor:v1.23.2-debug
    entrypoint: [""]
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --build-arg http_proxy=$http_proxy
      --build-arg https_proxy=$https_proxy
      --build-arg no_proxy=$no_proxy
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
  rules:
    - if: $CI_COMMIT_TAG

构建多架构镜像

你可以通过使用 manifest-tool 在容器内构建多架构镜像。

使用自定义证书的注册表

当尝试推送到使用自定义 CA 签署的证书的 Docker 注册表时,可能会收到以下错误:

$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push
INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image
error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority

可以通过将你的 CA 证书添加到 kaniko 证书存储来解决此问题:

before_script:
  - |
    echo "-----BEGIN CERTIFICATE-----
    ...
    -----END CERTIFICATE-----" >> /kaniko/ssl/certs/ca-certificates.crt

故障排除

403 错误:“检查推送权限时出错”

如果收到此错误,可能是由于外部代理导致的。设置 http_proxyhttps_proxy 环境变量 可以解决此问题。

错误:kaniko 应该仅在容器内运行

Docker Engine 20.10 引入了一个已知的不兼容性。

当主机使用 Docker Engine 20.10 或更新版本时,版本低于 v1.9.0 的 gcr.io/kaniko-project/executor:debug 镜像无法按预期工作。

当你尝试构建镜像时,Kaniko 会失败并显示以下信息:

kaniko should only be run inside of a container, run with the --force flag if you are sure you want to continue

要解决此问题,请将 gcr.io/kaniko-project/executor:debug 容器更新到至少 v1.9.0 的版本,例如 gcr.io/kaniko-project/executor:v1.23.2-debug

相反的配置(gcr.io/kaniko-project/executor:v1.23.2-debug 镜像和版本为 19.06.x 或更早版本的主机上的 Docker Engine)可以正常工作。为了获得最佳策略,你应该经常测试并更新作业环境版本到最新。这带来了新功能、提高的安全性,并且 - 对于这种特定情况 - 使 runner 主机上底层 Docker Engine 的升级对作业是透明的。