使用 kaniko 构建 Docker 镜像

kaniko 是一种在容器或 Kubernetes 集群内从 Dockerfile 构建容器镜像的工具。

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

  • Docker-in-Docker 需要特权模式才能运行,这是一个重要的安全问题。
  • Docker-in-Docker 通常会导致性能下降,而且速度可能非常慢。

要求

要将 kaniko 与极狐GitLab 一起使用,需要 runner 和以下 runner 之一:

  • Kubernetes
  • Docker
  • Docker Machine

使用 kaniko 构建 Docker 镜像

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

  • 推荐使用 kaniko debug 镜像 (gcr.io/kaniko-project/executor:debug),因为它有一个 shell,并且一个镜像需要一个 shell 才能与 GitLab CI/CD 一起使用。
  • Entrypoint 需要被覆盖,否则构建脚本不会运行。

在以下示例中,kaniko 用于:

  1. 构建 Docker 镜像。
  2. 然后推送到 GitLab Container Registry

作业仅在推送标签时运行。在 /kaniko/.docker 下创建了一个 config.json 文件,其所需的 GitLab Container Registry 凭据取自 GitLab CI/CD 提供的预定义的 CI/CD 变量

在最后一步中,kaniko 使用项目根目录下的 Dockerfile,构建 Docker 镜像并将其推送到项目的 Container Registry,同时使用 Git 标签对其进行标记:

build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:v1.9.0-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')\"},\"$CI_DEPENDENCY_PROXY_SERVER\":{\"auth\":\"$(printf "%s:%s" ${CI_DEPENDENCY_PROXY_USER} "${CI_DEPENDENCY_PROXY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json

在代理后面使用 kaniko 构建镜像

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

  • 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.9.0-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 registry 时,您可能会收到以下错误:

$ /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/additional-ca-cert-bundle.crt

故障排查

403 error: “error checking push permissions”

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