跳至主要内容

Image Building Tools Comparison

簡介

在這篇文章中,將會簡介目前常見的五種 Image Building Tools,分別是目前最常見的 Docker 以及新版本內建的 Buildkit、以及常被用在 CICD 過程中的三套 Build tool:Dind(Docker in Docker), Buildah, Kaniko 作比較。

比較這些上述五項 Image Building Tools 在 build image 時所花費的系統資源,如下述三項指標:

  • Memory(有 cache/ 無 cache)
  • Build Time
  • CPU time

並比較 build 完成後,Image Size 是否有所不同,並探討其中的差異。

測試環境

本次 lab 統一使用 CNTUG Infra Labs OpenStack 上的 VM,規格如下:

  • Linux version: Ubuntu 20.04
  • vCPU: 4 cores
  • RAM:4 G
  • total Disk:30 GB

測試方法會在下方 Labs 區塊中詳述

測試的 Image

本次 lab 使用 php-fpm 做 image build tool 的數據比較:

image namephp-fpm
versionphp 8.1
base imagealpine 3.16

各項工具簡介

Docker

為目前十分常見的 container solution,榮獲 2022 年 Stack Overflow 開發者大調查開發者最愛工具的第一名,功能齊全,在使用上透過 docker 指令進行 container 相關的各種操作。

Buildkit

Buildkit 為 Docker 推出的實驗性功能,主打更高效能、並行的運作方式,也針對 cache, storage management 等功能做了許多優化,加速了以往使用 Docker build image 的流程以及最佳化使用體驗,預設內建在 Docker 18.09 版本之後的 Docker 內,啟用方式也十分簡易,DOCKER_BUILDKIT=1 docker build . 即可使用,在 MacOS/Linux 環境下,也可透過建立 /etc/docker/daemon.json,並加入以下設定啟用 Buildkit。

{
  "features": {
    "buildkit" : true
  }
}

DinD

全名為 Docker-in-Docker,顧名思義,在 Docker 中再運行一個 Docker container,因此在運行起來的 container 內,也能執行 docker 指令,通常會在運行 CICD pipeline 時使用,好處是環境隔離,每次會起新的 Docker daemon,但 build 的時候無法共享 cache,但可以透過 cache-from 去指定特定的 image 加入 build 流程。

Buildah

Buildah 是由 Red Hat 開發,幫助開發者 build 相容 OCI 標準的 container images 的一套工具,在 podman 中預設會安裝 Buildah,但也可以單獨安裝使用,在使用上不須相依於 Dockerfile,而是能指定任意包含 build command 的檔案,可直接掛載 container,並對其內容進行操作,增加使用彈性、安全性。

詳細功能介紹可參考官方 Repo

Kaniko

可參考之前 Lab 撰寫的 Kaniko 教學,Kaniko 適合在 container 或是 k8s cluster 內 build image。

Labs

資源計算

  • CPU:在計算 CPU 使用率的部分,透過 Pseudo-files 的方式,每次在 build image 時,讀取 /sys/fs/cgroup/cpuacct/<TOOL_NAME>/$CONTAINER_ID/cpuacct.usage 去比較 CPU 使用的資源量。
  • Memory:使用 time 指令 /usr/bin/time -v 列出單一指令消耗的資源,每項工具以同樣的 build 指令執行 15 次,比較最大值、最小值、平均值。
  • Image size:在比較過多套 container image 分析工具後,選擇使用 Docker 內建的列出 docker image ls 查看 image size。
  • build time: 使用 time 指令 /usr/bin/time -v 查看其中的 Elapsed (wall clock) time,同樣比較最大值、最小值、平均值。

Docker

安裝的版本為 20.10.17,主要比較有無 layer caching 的 build process

  • 預設有 cache docker build -t <image-name>:<version> .
  • 不使用 cache docker build -t <image-name>:<version> . --no-cache

DinD

首先運行一個 dind container,並將 Dockerfile 等內容 mount 到 container 內,並開 shell 進到 dind container 中,再 build image,同樣比較有無 layer caching,此處使用 --cache-from 前面 build 好的 image 以加速 build 流程。

$ docker run -v $PWD:/workspace --privileged -d --name dind-test docker:dind
$ docker exec -it dind-test /bin/sh
$ cd workspace
$ docker build -t <image-name>:<version> .

# build image with cache
$ docker build -t <pre-existing-image-name>:<version> . --cache-from <image-name>:<version>

Buildkit

啟用 Buildkit 後,再下跟 docker build 一樣的指令即可,如果有下載 Docker Desktop,則預設就會啟用

$ DOCKER_BUILDKIT=1 docker build .

Buildah

先單獨安裝 Buildah,再下 buildah bud 即可開始 build image

# 安裝 Buildah
$ sudo apt install buildah
# build image
$ buildah bud -t <image-name>:<version> .
# build image with layers cache
$ buildah bud -t <image-name>:<version> --layers .
# 列出 build 好的 image
$ buildah images

Kaniko

使用 Docker 運行 kaniko v1.8.1 的 container,並將 build 好的 image 推到 Dockerhub 上

$ docker run -v $PWD:/workspace \
  -v ~/.docker/config.json:/kaniko/config.json \
  --env DOCKER_CONFIG=/kaniko gcr.io/kaniko-project/executor:v1.8.1 \
  -d <username>/<image-name>:<version>

測試結果

CPU Usage

CPU 資源使用量的部分,如上面 lab 區塊提到,看的檔案是 cpu usagecpu usage 為 lab 使用的環境:vCPU*4 的資源使用總和,且 build 過程中皆無使用 cache,比較結果如下:

  • 平均/最大/最小使用資源,單位為毫秒 (millisecond) CPU Usage

從上圖可以看到 Kaniko、Buildah 使用的資源低於 Docker,且略勝 Buildkit,以平均使用量來排序: Docker>Dind>Buildkit>Kaniko>Buildah

Memory

比較所使用的 memory,並分為 build 過程是否有使用 cache,至於 kaniko 的部分因目前尚未實作 local layer caching,因此此處僅計算沒有 cache 的 memory 使用部分。

  • 平均/最大/最小使用資源,單位為 Mib

  • 有 cache

memory Usage

  • 沒有 cache

memory Usage

從上面兩張圖可以看到在有 cache 的情況下,Dind 的記憶體使用率明顯高於其他 build tool,排除 Dind,使用率平均最低的則是 Buildah 接著是 Kaniko。但在沒有 cache 的情況下,Buildah 卻遠高於其他的 build tool。

Build Time

Build time 的部分同樣比較有無使用 cache 的情況。

在有使用到 build cache 的情況下,Docker/ BuildKit/ Kaniko 都是在一秒內 build 完,Buildah 則是平均 6 秒,因此此處並無製作圖表,僅製作沒有 cache 的情況下花費的時間做比較。

  • 單位為秒

build time

Docker cache 機制

Dockerfile 中的每條指令可視為一個 layer,在 build 的過程中會比較 Layer 與之前是否相同,若相同在使用 docker build 時會顯示 Using cache 以及使用了哪個 cache,cahce 則會存在 /var/lib/docker/image/overlay2/imagedb/content/sha256 底下,若是使用 BuildKit,則會顯示 CACHED,並拿之前的 build cache 來用,可以大幅減少 build image 的時間,若是 Dockerfile 內容有更改或是使用到的檔案內容有更改就不用使用到 cache,而是會重新 build layer,且後續的 layer 也會需要重新 build,因此在撰寫 Dockerfile 時可以將比較常更改的內容放在 Dockerfile 尾端。

Image Size

在 image size 的部分則可以發現差別並不大

  • 單位為 MB

image size

各項工具比較

DinDKanikoBuildahBuildKit
Run without privileged modeXOOO
Local layer cachingXXOO
Remote layer cachingOOOO
Need dockerfileOOXO

小結

在此次 lab 中,比較了不同 build tool 的資源使用量以及 build 出來的 image size 以及花費的時間,可以發現每個 build tool 各有優缺,也有一些 tool 的資源使用量與想像的有所不同,但無可否認的是這些工具發展十分迅速,在找資料時也發現有些原本被開發人員詬病的特性已經被修掉了,容器安全性的疑慮也有了其他解法,因此,最佳解仍然是根據開發及維運人員的環境及需求去選擇適合的工具。

Reference