Post

用 Docker BuildKit 替換 Kaniko

Kaniko 已停止維護?如何以 Docker BuildKit 取代。從原理、cache 機制到 GitLab CI 實作範例。

用 Docker BuildKit 替換 Kaniko

TL;DR

原本使用的 Kaniko 已經 Archived
Survey Dcoker BuildKit
包含 Command Line, Cache, GitLab-CI 與相關設定

Docker BuildKit 概觀

BuildKit 相比傳統 Docker 的優化

可以處理更複雜的情境,包含

  • 跳過未使用的 Stage
  • 平行打包無相依性的 Stage
  • 僅同步有異動的檔案至 Stage
  • 僅同步 build context 內有被使用到的檔案

BuildKit 是什麼?

BuildKit 是 Low-Level Build(LLB) 例如 DockerfileMockerfile 都經過編譯成 LLB 後,才實際執行打包建構 convert-export

三種 Docker build 指令比較

  • docker buildx build
    • 其中最 High-Level 的指令
    • ❌ 需要 Daemon
    • ❌ 不支援 root-less
  • buildctl build
    • 比起 docker build 稍為更低階一點
    • ❌ 需要 Daemon
    • ❌ 不支援 root-less
  • buildctl-daemonless.sh build
    • 其中最低階
    • ✅ 無需 Daemon
    • ✅ 支援 root-less
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
##### 指令範例 #####

# Traditional Docker
docker buildx build -t myimage:latest . --push

# buildctl
buildctl build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --output type=image,name="myimage:latest",push=true

# daemonless
buildctl-daemonless.sh build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --output type=image,name="myimage:latest",push=true

Cache 機制

1
2
3
4
5
6
7
# syntax=docker/dockerfile:1
FROM ubuntu:latest

RUN apt-get update && apt-get install -y build-essentials
COPY main.c Makefile /src/
WORKDIR /src/
RUN make build

當有任何一個 Layer 的內容變動,該 Layer 與後續 Layer 會需要 re-build docker-layer 例如 main.c 的內容異動 → COPY 之後的 Layer 皆需 re-build cache-layer

Cache 種類 cache-type

指令範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
##### 一般情境 #####
tree
.
├── main.c
├── Makefile
└── Dockerfile

buildctl-daemonless.sh build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --output type=image,name="myimage:latest",push=true


##### 當 Dockerfile 不在 root #####
tree
.
├── build
│   └── Dockerfile
├── main.c
└── Makefile

buildctl-daemonless.sh build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --opt filename=build/Dockerfile \
    --output type=image,name="myimage:latest",push=true

##### 建立 cache #####
tree
.
├── main.c
├── Makefile
└── Dockerfile

CACHE_IMAGE=$CI_REGISTRY_IMAGE:cache
buildctl-daemonless.sh build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --export-cache type=registry,ref=$CACHE_IMAGE \
    --import-cache type=registry,ref=$CACHE_IMAGE \
    --output type=image,name="myimage:latest",push=true

##### 建構多平臺 #####
buildctl-daemonless.sh build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --opt platform=linux/amd64,linux/arm64 \
    --output type=image,name="myimage:latest",push=true

##### 參數帶入 #####
buildctl-daemonless.sh build \
    --frontend dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --build-arg no_proxy=$no_proxy \
    --output type=image,name="myimage:latest",push=true

GitLab-CI 範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
build:
  stage: build
  image: moby/BuildKit:rootless
    name: BuildKit
    entrypoint: [""]
  variables:
    DOCKERFILE_PATH: "build/Dockerfile"
    CACHE_IMAGE: $CI_REGISTRY_IMAGE:cache
    BuildKitD_FLAGS: --oci-worker-no-process-sandbox
  script:
    - !reference [.docker-login]
    - !reference [.prepare-image-name]
    - |
      buildctl-daemonless.sh build \
        --frontend dockerfile.v0 \
        --local context=. \
        --local dockerfile=. \
        --opt filename=${DOCKERFILE_PATH} \
        --export-cache type=registry,ref=$CACHE_IMAGE \
        --import-cache type=registry,ref=$CACHE_IMAGE \
        --output type=image,name=$IMAGE_WITH_TAG,push=true
  allow_failure: false

指令參數說明

Docker context: 讓 Docker 知道能 access 的檔案範圍

1
2
docker build [OPTIONS] PATH | URL
                       ^^^^^^^^^^

📌 關鍵字:Docker BuildKit、Kaniko 替代方案、buildctl、daemonless、GitLab CI、container build、Docker cache、multi-platform build、moby/BuildKit、CI/CD pipeline、buildx

This post is licensed under CC BY 4.0 by the author.