用buildkit和containerd构建镜像

最近因为K8s抛弃Docker了,所以就只装了个containerd,这样就需要一个单独的镜像构建工具了,就用了buildkit,这也是Docker公司扶持的,他们公司的人出来搞的开源工具,官网在 github.com/moby/buildki

架构及限制

  1. 服务端为buildkitd,负责和runc或containerd后端连接干活,目前只支持这两个后端
  2. 客户端为buildctl,负责解析镜像构建文件Dockerfile,并向服务端发出构建指令,所以客户端可以和服务端不在一台机器上,也不需要root权限之类
  3. 服务端默认使用runc后端,但是建议使用containerd后端,这样构建出的镜像就会存在containerd的buildkit名字空间下

下载安装

  1. 官网没看到源, 所以只能用绿色包了 Releases · moby/buildkit
  2. 去官网下载一个最新的包 buildkit-v0.8.2.linux-amd64.tar.gz ,解压后得到一个bin目录
  3. 把这个bin目录放到 $PATH 里去

启动buildkitd服务

buildkitd默认运行在前台的,如果需要后面加一个 &

用参数启动

使用 --oci-worker=false --containerd-worker=true 参数,可以让buildkitd服务使用containerd后端

buildkitd --oci-worker=false --containerd-worker=true & 

使用配置文件启动

创建配置文件

mkdir -p /etc/buildkit/
vim /etc/buildkit/buildkitd.toml

配置使用containerd后端,禁用oic后端,并把默认名字空间改为"default"(这是为了以后和nerdctl配合使用),把平台限制为本机类型amd64,配置垃圾回收空间限制

[worker.oci]
  enabled = false

[worker.containerd]
  enabled = true
  # namespace should be "k8s.io" for Kubernetes (including Rancher Desktop)
  namespace = "default"
  platforms = [ "linux/amd64" ]
  gc = true
  # gckeepstorage sets storage limit for default gc profile, in MB.
  gckeepstorage = 9000

用此配置启动服务

buildkitd --config /etc/buildkit/buildkitd.toml & 

把buildkitd配置成系统服务

参考 github.com/moby/buildki

首先,把 之前下载解压出来的bin目录里的文件拷贝到系统目录下(那个目录里其他文件用不上)

cd bin
cp buildctl /usr/local/bin
cp buildkitd /usr/local/bin

增加服务配置文件

vim /usr/lib/systemd/system/buildkit.service

如下

[Unit]
Description=BuildKit
Requires=buildkit.socket
After=buildkit.socket
Documentation=https://github.com/moby/buildkit

[Service]
Type=notify
ExecStart=/usr/local/bin/buildkitd --addr fd://

[Install]
WantedBy=multi-user.target

增加socket配置文件

vim /usr/lib/systemd/system/buildkit.socket

如下

[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Socket]
ListenStream=%t/buildkit/buildkitd.sock
SocketMode=0660

[Install]
WantedBy=sockets.target

激活并启动服务

systemctl enable buildkit
systemctl start buildkit

注意:如果配置文件 /etc/buildkit/buildkitd.toml 存在,服务启动时会自动装载该配置文件

构建本地镜像

buildctl build \
    --frontend=dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --output type=image,name=docker.io/username/image:tag

解释:

  1. frontend可以使用网关做前端,未做其他尝试,这里直接使用dockerfile.0
  2. --local context 指向当前目录,这是Dockerfile执行构建时的路径上下文,比如在从目录中拷贝文件到镜像里
  3. --local dockerfile指向当前目录,表示Dockerfile在此目录
  4. --output 的 name 表示构建的镜像名称
  5. 构建完成后镜像会存在本地containerd的buildkit名字空间或配置文件指定的名字空间下

使用nerdctl构建本地镜像

参见 How:nerdctl安装和使用

查看本地镜像

ctr -n buildkit i ls

注意:

  1. ctr是containerd自带的命令行工具,除了构建镜像不能干,其他docker-cli的活它都可以干
  2. 因为buildkitd的后端选择了containerd,本地镜像会去到containerd的本地存储
  3. 默认本地镜像都存在buildkit名字空间下,要修改此名字空间, 可以去配置 /etc/buildkit/buildkitd.toml

使用ctr推送镜像

ctr -n buildkit i push -u username:password docker.io/username/image:tag

注意:

  1. ctr推送时直接把registry的帐号密码当成参数 -u
  2. 参数中的帐号密码是明码的,慎用

构建镜像并推送到registry

registry的帐号密码配置在 ~/.docker/config.json 文件中 , 沿用了Docker的配置,虽然我们并没有装Docker

{
        "auths": {
                "docker.io": {
                        "auth": "base64(username:password)"
                }
        }
}

执行构建并推送到registry

buildctl build \
    --frontend=dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --output type=image,name=docker.io/username/image:tag,push=true

解释:

  1. --output 的 name 表示构建的镜像名称
  2. --output 的 push=true,表示构建镜像后推送到服务器
  3. 本地镜像仍然会存储在containerd的buildkit名字空间下

使用缓存构建镜像并推送到registry

buildctl build \
    --frontend=dockerfile.v0 \
    --local context=. \
    --local dockerfile=. \
    --output type=image,name=docker.io/username/image:tag,push=true
    --export-cache type=inline

注意:

  1. --export-cache 的 type=inline 表示把缓存放到镜像里,一起推送到registry
  2. 加上此参数后,似乎构建和推送的速度都并没有更快, 可能我还没有透彻理解, 等有空再看看
  3. --export-cache 还有两种type,暂时未做尝试
  4. 还有--import-cache的参数,暂时也未作尝试

镜像大小

以目前短暂的经验,buildkit构建的镜像一般至少会比Docker构建的镜像小10% , 最多的会小50% 多.

延伸阅读

编辑于 2022-12-12 19:45・IP 属地广东