buildkit:高效的容器镜像构建工具

buildkit:高效的容器镜像构建工具

在现代容器化应用开发中,构建容器镜像是重要的一环。随着应用复杂度的增加,开发者需要更高效、灵活的构建工具来满足多平台支持、资源优化以及更安全的需求。

BuildKit 是 Docker 推出的新一代容器镜像构建工具,它以并行构建、多平台支持和改进的缓存机制,迅速成为开发者首选。

什么是 BuildKit?

BuildKit 是 Docker 构建工具的核心组件,主要用于优化镜像构建的性能和灵活性。与传统的 Docker 镜像构建流程相比,BuildKit 提供以下优势:

​ 1. 并行构建:支持多任务并行处理,显著减少构建时间。

​ 2. 多平台支持:一次性构建多架构(如 amd64 和 arm64)的镜像。

​ 3. 改进的缓存机制:支持细粒度缓存控制,提高重复构建的效率。

​ 4. 更灵活的配置:通过 buildkitd.toml 文件自定义构建行为,满足不同场景需求。

虽然之前介绍的 Kaniko 🔗 也是一种支持无守护进程(Daemonless)容器构建的工具,但它在多架构镜像构建方面存在局限性。

例如,在同时构建 linux/amd64linux/arm64 架构时,Kaniko 需要分别构建两个镜像再手动合并,流程略显繁琐。相比之下,BuildKit 原生支持多架构构建,同时兼容多种平台(如 Linux、Windows、macOS 等),并能无缝集成到 Podman、Nerdctl 和 Kubernetes 中。此外,BuildKit 支持 Daemonless 和 Rootless 模式,为开发者提供了更高的灵活性和安全性。

Buildkit的使用(Kubernetes + job)

以下以 Kubernetes + Job 🔗 的形式(Daemonless + Rootless 模式)为例,说明 BuildKit 的使用方法。

配置授权信息

BuildKit 使用的授权信息与 Docker 一致,存储在 $DOCKER_CONFIG/config.json 文件中,其中 DOCKER_CONFIG 的默认路径为 ~/.docker。以下是配置文件的示例:

{
  "auths": {
    "192.168.100.26:30003": {
      "auth": "******"
    }
  }
}

可以在运行的时候指定环境变量DOCKER_CONFIG即可,例如:

apiVersion: batch/v1
kind: Job
metadata:
  name: buildkit
spec:
  template:
    spec:
      containers:
        - name: buildkit
          image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/buildkit:v0.18.2-rootless
          env:
            - name: DOCKER_CONFIG
              value: /workspace

配置HTTP registry

如果使用镜像镜像仓库是通过HTTP访问的(非HTTPS类型),那么需要额外配置buildkitd.toml 🔗配置文件。

对于rootless模式,需要将配置文件保存在~/.config/buildkit/buildkitd.toml,完整路径通常为/home/user/.config/buildkit/buildkitd.toml,例如:

cat > /home/user/.config/buildkit/buildkitd.toml <<EOF
[registry."192.168.100.26:30003"]
http = true
insecure = true
EOF

这能够解决Dockerfile中FROM后的镜像仓库为HTTP却无法拉取的原因

配置HTTPS registry

如果使用镜像镜像仓库是通过HTTPS访问的,但是确实自签名证书,需要在构建的时候增加参数--registry-auth-tlscontext host=hb.example.com,insecure=true,通过 insecure=true 配置,可跳过 TLS 验证,但需谨慎使用,仅在受信任环境中启用。

配置Job

apiVersion: batch/v1
kind: Job
metadata:
  name: buildkit
spec:
  backoffLimit: 0
  # 3天后 删除
  ttlSecondsAfterFinished: 259200
  template:
    metadata:
      annotations:
        container.apparmor.security.beta.kubernetes.io/buildkit: unconfined
    spec:
      restartPolicy: Never
      initContainers:
        - name: prepare-dockerfile
          image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/bash:5
          command:
            - sh
            - -c
            - |
              cat > /workspace/Dockerfile <<EOF
              FROM 192.168.100.26:30003/library/bash:5
              EOF
          securityContext:
            runAsUser: 1000
            runAsGroup: 1000
          volumeMounts:
            - name: workspace
              mountPath: /workspace
        - name: prepare-docker-config
          image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/bash:5
          command:
            - /bin/sh
            - -c
            - "echo '{\"auths\":{\"192.168.100.26:30003\":{\"auth\":\"*****\"}}}' > /workspace/config.json && cat /workspace/config.json"
          securityContext:
            runAsUser: 1000
            runAsGroup: 1000
          volumeMounts:
            - mountPath: /workspace
              name:  workspace
        - name: prepare-toml
          image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/bash:5
          command:
            - /bin/sh
            - -c
            - |
              cat > /home/user/.config/buildkit/buildkitd.toml <<EOF
              [registry."192.168.100.26:30003"]
              http = true
              insecure = true
              EOF
          securityContext:
            runAsUser: 1000
            runAsGroup: 1000
          volumeMounts:
            - mountPath: /home/user/.config/buildkit
              name:  buildkit
      containers:
        - name: buildkit
          image: swr.cn-east-3.myhuaweicloud.com/lomtom-common/buildkit:v0.18.2-rootless
          env:
            - name: BUILDKITD_FLAGS
              value: --oci-worker-no-process-sandbox
            - name: DOCKER_CONFIG
              value: /workspace
          command:
            - buildctl-daemonless.sh
          args:
            - build
            - --frontend
            - dockerfile.v0
            - --local
            - context=/workspace
            - --local
            - dockerfile=/workspace
            - --opt
            - platform=linux/amd64,linux/arm64
            - --output
            - type=image,name=192.168.100.26:30003/lomtom/bash:5,push=true
            - --registry-auth-tlscontext
            - host=192.168.100.26:30003,insecure=true
          securityContext:
            # Needs Kubernetes >= 1.19
            seccompProfile:
              type: Unconfined
            # To change UID/GID, you need to rebuild the image
            runAsUser: 1000
            runAsGroup: 1000
          volumeMounts:
            - name: workspace
              mountPath: /workspace
            - name:  buildkit
              mountPath: /home/user/.config/buildkit
      volumes:
        - name: workspace
          emptyDir: {}
        - name: buildkit
          emptyDir: {}

其中:在 initContainers 中设置了多个初始化容器:

  • prepare-dockerfile:动态生成 Dockerfile。
  • prepare-docker-config:配置私有镜像仓库的认证信息。
  • prepare-toml:配置 buildkitd.toml 文件,支持 HTTP 和不安全模式的私有镜像仓库。

参数:

  • platform:指定构建的架构
  • output:指定构建结果,这里为image类型,并且创建镜像后推送
  • registry-auth-tlscontext:该参数允许在无安全认证的环境中构建和推送镜像。通过 insecure=true 配置,可跳过 TLS 验证,但需谨慎使用,仅在受信任环境中启用。

日志:

1 [internal] load build definition from Dockerfile
1 transferring dockerfile: 131B done
1 DONE 0.1s

2 [auth] library/bash:pull token for 192.168.100.26:30003
2 DONE 0.0s

3 [linux/amd64 internal] load metadata for 192.168.100.26:30003/library/bash:5
3 ...

4 [linux/arm64 internal] load metadata for 192.168.100.26:30003/library/bash:5
4 DONE 0.7s

3 [linux/amd64 internal] load metadata for 192.168.100.26:30003/library/bash:5
3 DONE 0.8s

5 [internal] load .dockerignore
5 transferring context: 2B done
5 DONE 0.0s

6 [linux/amd64 1/1] FROM 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368
6 resolve 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368 0.0s done
6 DONE 0.1s

7 [linux/arm64 1/1] FROM 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368
7 resolve 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368 0.0s done
7 DONE 0.1s

8 [auth] lomtom/bash:pull,push token for 192.168.100.26:30003
8 DONE 0.0s

9 exporting to image
9 exporting layers done
9 exporting manifest sha256:97e41d808c474ec951f03d2b42043d02e9b90e1113c00385d496cc93e3b404fb done
9 exporting config sha256:bd4206c5bc03671d4628a19a518f7e4c7ddf5ff8026fc035188b9615386f6df1 done
9 exporting manifest sha256:db3f28b9b1bdf1c6ba413b6f94e97339a1fe84efe5272382a1750f1fc2565c68 done
9 exporting config sha256:5c664b1446dec19998870821e26efedfce64b394040431c38a08531b78f73942 done
9 exporting manifest list sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368 done
9 pushing layers
9 pushing layers 0.2s done
9 pushing manifest for 192.168.100.26:30003/lomtom/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368
9 pushing manifest for 192.168.100.26:30003/lomtom/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368 0.8s done
9 DONE 1.1s

Buildkit的使用(主机 + rootful)

安装

buildkitdBuildKit 由守护进程和客户端组成buildctlbuildctl客户端可用于 Linux、macOS 和 Windows,而buildkitd守护进程目前仅适用于 Linux 和 *Windows。

适用于 Linux、macOS 和 Windows的 BuildKit 最新二进制文件可在此处获取。 🔗

# 下载
wget https://github.com/moby/buildkit/releases/download/v0.18.2/buildkit-v0.18.2.linux-amd64.tar.gz
# 解压
mkdir /usr/local/buildkit
tar -xf buildkit-v0.18.2.linux-amd64.tar.gz -C /usr/local/buildkit
# 配置环境变量
echo 'export PATH=/usr/local/buildkit/bin:$PATH' >> /etc/profile
source /etc/profile

配置

对于rootful模式,需要将配置文件保存在/etc/buildkit/buildkitd.toml

# 配置buildkitd.toml文件
mkdir /etc/buildkit
cat > /etc/buildkit/buildkitd.toml <<EOF
[registry."192.168.100.26:30003"]
http = true
insecure = true
EOF

配置buildkit自启动服务

cat <<EOF > /usr/lib/systemd/system/buildkitd.service
[Unit]
Description=buildkitd
After=network.target

[Service]
ExecStart=/usr/local/buildkit/bin/buildkitd  --config=/etc/buildkit/buildkitd.toml

[Install]
WantedBy=multi-user.target
EOF


# 重新加载Unit file
systemctl daemon-reload
# 启动服务
systemctl start buildkitd
# 开机自启动
systemctl enable buildkitd

如果要buildkitd以非 root 用户身份运行,请自行参考:rootless模式 🔗

测试验证

cat > ./Dockerfile <<EOF
FROM 192.168.100.26:30003/library/bash:5
EOF

buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt platform=linux/amd64,linux/arm64 \
--output type=image,name=test:latest \
--registry-auth-tlscontext host=192.168.100.26:30003,insecure=true

参数:

  • platform:指定构建的架构
  • output:指定构建结果,这里为image类型
  • registry-auth-tlscontext:该参数允许在无安全认证的环境中构建和推送镜像。通过 insecure=true 配置,可跳过 TLS 验证,但需谨慎使用,仅在受信任环境中启用。

日志:

[+] Building 0.5s (7/7) FINISHED                                                                                                                                                                        
 => [internal] load build definition from Dockerfile                                                                                                                                               0.0s
 => => transferring dockerfile: 78B                                                                                                                                                                0.0s
 => [linux/arm64 internal] load metadata for 192.168.100.26:30003/library/bash:5                                                                                                                   0.3s
 => [linux/amd64 internal] load metadata for 192.168.100.26:30003/library/bash:5                                                                                                                   0.1s
 => [internal] load .dockerignore                                                                                                                                                                  0.0s
 => => transferring context: 2B                                                                                                                                                                    0.0s
 => [linux/arm64 1/1] FROM 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368                                                             0.1s
 => => resolve 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368                                                                         0.0s
 => CACHED [linux/amd64 1/1] FROM 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368                                                      0.0s
 => => resolve 192.168.100.26:30003/library/bash:5@sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368                                                                         0.0s
 => exporting to image                                                                                                                                                                             0.0s
 => => exporting layers                                                                                                                                                                            0.0s
 => => exporting manifest sha256:97e41d808c474ec951f03d2b42043d02e9b90e1113c00385d496cc93e3b404fb                                                                                                  0.0s
 => => exporting config sha256:bd4206c5bc03671d4628a19a518f7e4c7ddf5ff8026fc035188b9615386f6df1                                                                                                    0.0s
 => => exporting manifest sha256:db3f28b9b1bdf1c6ba413b6f94e97339a1fe84efe5272382a1750f1fc2565c68                                                                                                  0.0s
 => => exporting config sha256:5c664b1446dec19998870821e26efedfce64b394040431c38a08531b78f73942                                                                                                    0.0s
 => => exporting manifest list sha256:1ed86e5fdfd1868db6926222367e8bf95951d77e2369d2248ccaef0935c3d368                                                                                             0.0s

总结

BuildKit 的出现极大地提升了容器镜像构建的效率和灵活性,是现代容器化开发环境中的重要工具。无论是在本地开发还是云原生环境中,BuildKit 都能帮助开发者构建高质量的镜像,为应用交付提供强有力的支持。

  1. Failed to pull image from self-signed certificate registry 🔗
  2. daemonless: cannot add private repository certificates 🔗
lomtom

标题:buildkit:高效的容器镜像构建工具

作者:lomtom

链接:https://lomtom.cn/vrqlkpdd61y0