用buildkit和containerd构建镜像
最近因为K8s抛弃Docker了,所以就只装了个containerd,这样就需要一个单独的镜像构建工具了,就用了buildkit,这也是Docker公司扶持的,他们公司的人出来搞的开源工具,官网在 https://github.com/moby/buildkit
架构及限制
- 服务端为buildkitd,负责和runc或containerd后端连接干活,目前只支持这两个后端
- 客户端为buildctl,负责解析镜像构建文件Dockerfile,并向服务端发出构建指令,所以客户端可以和服务端不在一台机器上,也不需要root权限之类
- 服务端默认使用runc后端,但是建议使用containerd后端,这样构建出的镜像就会存在containerd的buildkit名字空间下
下载安装
- 官网没看到源, 所以只能用绿色包了 Releases · moby/buildkit
- 去官网下载一个最新的包 buildkit-v0.8.2.linux-amd64.tar.gz ,解压后得到一个bin目录
- 把这个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配置成系统服务
参考 https://github.com/moby/buildkit/tree/master/examples/systemd/system
首先,把 之前下载解压出来的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
解释:
- frontend可以使用网关做前端,未做其他尝试,这里直接使用dockerfile.0
- --local context 指向当前目录,这是Dockerfile执行构建时的路径上下文,比如在从目录中拷贝文件到镜像里
- --local dockerfile指向当前目录,表示Dockerfile在此目录
- --output 的 name 表示构建的镜像名称
- 构建完成后镜像会存在本地containerd的buildkit名字空间或配置文件指定的名字空间下
使用nerdctl构建本地镜像
查看本地镜像
ctr -n buildkit i ls
注意:
- ctr是containerd自带的命令行工具,除了构建镜像不能干,其他docker-cli的活它都可以干
- 因为buildkitd的后端选择了containerd,本地镜像会去到containerd的本地存储
- 默认本地镜像都存在buildkit名字空间下,要修改此名字空间, 可以去配置
/etc/buildkit/buildkitd.toml
使用ctr推送镜像
ctr -n buildkit i push -u username:password docker.io/username/image:tag
注意:
- ctr推送时直接把registry的帐号密码当成参数 -u
- 参数中的帐号密码是明码的,慎用
构建镜像并推送到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
解释:
- --output 的 name 表示构建的镜像名称
- --output 的 push=true,表示构建镜像后推送到服务器
- 本地镜像仍然会存储在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
注意:
- --export-cache 的 type=inline 表示把缓存放到镜像里,一起推送到registry
- 加上此参数后,似乎构建和推送的速度都并没有更快, 可能我还没有透彻理解, 等有空再看看
- --export-cache 还有两种type,暂时未做尝试
- 还有--import-cache的参数,暂时也未作尝试
镜像大小
以目前短暂的经验,buildkit构建的镜像一般至少会比Docker构建的镜像小10% , 最多的会小50% 多.
延伸阅读
编辑于 2022-12-12 19:45・IP 属地广东