使用 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 需要被覆盖,否则构建脚本不会运行。
- 需要使用所需容器镜像库的身份验证信息创建 Docker
config.json
文件。
在以下示例中,kaniko 用于:
- 构建 Docker 镜像。
- 然后推送到 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:debug
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
在代理后面使用 kaniko 构建镜像
如果您在 http(s) 代理后面使用自定义 GitLab Runner,则需要相应地设置 kaniko。这意味着:
- 将代理添加到
/kaniko/.docker/config.json
- 将
http_proxy
环境变量作为构建参数传递,以便 Dockerfile 指令可以在构建镜像时使用代理。
前面的例子可以扩展如下:
build:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- |-
KANIKOPROXYBUILDARGS=""
KANIKOCFG="\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}"
if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then
KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}"
KANIKOPROXYBUILDARGS="--build-arg http_proxy=${http_proxy} --build-arg https_proxy=${https_proxy} --build-arg no_proxy=${no_proxy}"
fi
KANIKOCFG="{ ${KANIKOCFG} }"
echo "${KANIKOCFG}" > /kaniko/.docker/config.json
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
"${KANIKOPROXYBUILDARGS}"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
rules:
- if: $CI_COMMIT_TAG
使用带有自定义证书的镜像库
尝试推送到使用由自定义 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:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
- |
echo "-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt
故障排查
403 error: “error checking push permissions”
如果您收到此错误,则可能是由于外部代理。设置 http_proxy
和 https_proxy
环境变量可以解决问题。