极狐gitlab pipeline 构建容器镜像两大方法

极狐gitlab pipeline 构建容器镜像两大方法

随着 k8s 的流行,用容器的方式来交付软件产品也变得越来越普遍,那么在极狐gitlab ci/cd 流程中如何更快捷、更安全的方式来构建容器镜像呢?目前主要有两大的方式:

  • docker 构建镜像
  • Kaniko 构建镜像

1. docker 构建镜像

1.1 shell executor 方式

注册 runner,使用 shell executor

gitlab-runner register -n \
  --url https://jihulab.com/ \
  --registration-token REGISTRATION_TOKEN \
  --executor shell \
  --description "My Runner"

在 runner 主机上安装 docker:Install Docker Engine | Docker Documentation

添加 runner 到 docker 组

usermod -aG docker gitlab-runner

验证 gitlab-runner 用户是否能够访问 docker

sudo -u gitlab-runner -H docker info

在 pipeline 中使用 docker 打包镜像并上传到镜像仓库:

before_script:
  - docker info
  - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  rules:
    - if: $CI_COMMIT_TAG
  • 镜像仓库使用的时 gitlab 提供的 REGISTRY,也可以替换成自行搭建的仓库

  • 使用了 --cache 加速镜像构建

1.2 挂载 docker.sock 文件方式

使用 docker executor,runner 配置类似以下内容:

[[runners]]
  url = "https://jihulab.com/"
  token = RUNNER_TOKEN
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:19.03.12"
    privileged = false
    disable_cache = false
    volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
  [runners.cache]
    Insecure = false

使用以下注册方法可以生成上面配置内容:

gitlab-runner register -n \
  --url https://jihulab.com/ \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

在 pipeline 中使用 docker 打包镜像并上传到镜像仓库:

image: docker:19.03.12

before_script:
  - docker info
  - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  rules:
    - if: $CI_COMMIT_TAG

1.3 dind(docker-in-docker) 方式

这种方式不需要挂载宿主机的socket文件,但是需要以 --privileged 权限来以 dind 镜像创建一个容器

1.3.1 使用 docker executor

开启 TLS

docker 19.03.12 版本后,默认开启 TLS

runner 配置类似以下内容:

[[runners]]
  url = "https://jihulab.com/"
  token = TOKEN
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:19.03.12"
    privileged = true
    disable_cache = false
    volumes = ["/certs/client", "/cache"]
  [runners.cache]
    Insecure = false
  • privileged = true 必须

使用以下注册方法可以生成上面配置内容:

gitlab-runner register -n \
  --url https://jihulab.com/ \
  --registration-token REGISTRATION_TOKEN \
  --executor docker \
  --description "My Docker Runner" \
  --docker-image "docker:19.03.12" \
  --docker-privileged \
  --docker-volumes "/certs/client"

在 pipeline 中使用 docker in docker 打包镜像并上传到镜像仓库:

image: docker:19.03.12

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"

services:
  - docker:19.03.12-dind

before_script:
  - docker info
  - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  rules:
    - if: $CI_COMMIT_TAG

关闭 TLS

runner 配置类似以下内容:

[[runners]]
  url = "https://jihulab.com/"
  token = TOKEN
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "docker:19.03.12"
    privileged = true
    disable_cache = false
    volumes = ["/cache"]
  [runners.cache]
    Insecure = false

在 pipeline 中使用 docker in docker 打包镜像并上传到镜像仓库:

image: docker:19.03.12

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_HOST: tcp://docker:2375
  DOCKER_TLS_CERTDIR: ""

services:
  - docker:19.03.12-dind

before_script:
  - docker info
  - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  rules:
    - if: $CI_COMMIT_TAG

1.3.2 使用 kubernetes executor

开启 TLS

使用 Helm Chart 方式安装 runner,更新配置文件 values.yaml 加载证书目录

runners:
  config: |
    [[runners]]
      [runners.kubernetes]
        image = "ubuntu:20.04"
        privileged = true
      [[runners.kubernetes.volumes.empty_dir]]
        name = "docker-certs"
        mount_path = "/certs/client"
        medium = "Memory"

在 pipeline 中使用 docker in docker 打包镜像并上传到镜像仓库:

image: docker:19.03.12

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"
  DOCKER_TLS_VERIFY: 1
  DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
  
services:
  - docker:19.03.12-dind

before_script:
  - docker info
  - echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG -t $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
  rules:
    - if: $CI_COMMIT_TAG

2. Kaniko 构建镜像

使用 docker in docker 方式构建镜像时有以下问题:

  • 需要使用 privileged mode ,存在安全隐患
  • 因为需要额外运行 Docker daemon 进程,性能和速度上不太理想

Kaniko 是谷歌开源的一款用来构建容器镜像的工具。与 docker 不同,Kaniko 并不依赖于 Docker daemon 进程,完全是在用户空间根据 Dockerfile 的内容逐行执行命令来构建镜像,这就使得在一些无法获取 docker daemon 进程的环境下也能够构建镜像,比如在标准的Kubernetes Cluster上。

使用 kaniko,runner 只能使用以下类型的 executor:

2.1 使用 Kaniko 打包镜像

如果想使用 Kaniko 打包镜像,需要以下条件:

  • kaniko debug 镜像:gcr.io/kaniko-project/executor:debug,国内可能无法下载,可以使用 willdockerhub/kaniko-executor:debug 代替,也可以使用微软国内镜像源:gcr.azk8s.cn/kaniko-project/executor:debug(gcr.io 的镜像都可以使用这个方法下载)
  • entrypoint 必须重写 overridden,否则打包脚本无法运行
  • 需要配置 config.json,其中包含远程仓库的登陆认证信息

示例:

build:
  stage: build
  image:
    # name: gcr.io/kaniko-project/executor:debug
    name: willdockerhub/kaniko-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 帮助:docker run --rm willdockerhub/kaniko-executor:debug

2.2 自签证书 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

解决方法如下:

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
posted @   leffss  阅读(774)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示