BuildKit 镜像构建工具
快速开始
对于 Kubernetes 部署,请参阅examples/kubernetes。
BuildKit 由buildkitd守护进程和buildctl客户端组成。虽然buildctl客户端可用于 Linux、macOS 和 Windows,但buildkitd守护程序目前仅适用于 Linux。
该buildkitd守护程序需要安装以下组件:
- runc或crun
- 容器(如果你想使用容器工作)
此处提供适用于 Linux、macOS 和 Windows 的最新 BuildKit 二进制文件。
Homebrew 软件包(非官方)适用于 macOS。
$ brew install buildkit
要从源代码构建 BuildKit,请参阅.github/CONTRIBUTING.md。
有关buildctl参考,请参阅此文档。
启动buildkitd守护进程
您需要buildkitd在主机上以 root 用户身份运行。
$ sudo buildkitd
要buildkitd以非 root 用户身份运行,请参阅docs/rootless.md。
buildkitd 守护进程支持两个工作后端:OCI (runc) 和 containerd。
默认情况下,使用 OCI (runc) 工作线程。您可以设置--oci-worker=false --containerd-worker=true使用containerd工作线程。
我们愿意添加更多后端。
要使用 systemd 套接字激活来启动 buildkitd 守护进程,您可以安装 buildkit systemd 单元文件。请参阅Systemd 套接字激活
buildkitd 守护进程/run/buildkit/buildkitd.sock默认侦听 gRPC API,但您也可以使用 TCP 套接字。请参阅将 BuildKit 公开为 TCP 服务。
探索 Dockerfile
前端是在 BuildKit 内运行并将任何构建定义转换为 LLB 的组件。有一个称为 gateway ( gateway.v0) 的特殊前端,它允许使用任何图像作为前端。
在开发过程中,Dockerfile 前端 ( dockerfile.v0) 也是 BuildKit 存储库的一部分。将来,这将被移出,并且可以使用外部映像构建 Dockerfile。
使用以下命令构建 Dockerfilebuildctl
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=.
# or
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt target=foo \
--opt build-arg:foo=bar
--local将本地源文件从客户端公开给构建器。context和dockerfile是 Dockerfile 前端查找构建上下文和 Dockerfile 位置的名称。
如果 Dockerfile 有不同的文件名,则可以使用--opt filename=./Dockerfile-alternative.
使用外部前端构建 Dockerfile
Dockerfile 前端的外部版本被推送到https://hub.docker.com/r/docker/dockerfile-upstream和https://hub.docker.com/r/docker/dockerfile,并且可以与网关前端一起使用。外部前端的源当前位于此存储库中./frontend/dockerfile/cmd/dockerfile-frontend,但将来会移出此存储库(#163)。对于从该存储库的主分支自动构建,docker/dockerfile-upstream:master可以docker/dockerfile-upstream:master-labs使用图像。
buildctl build \
--frontend gateway.v0 \
--opt source=docker/dockerfile \
--local context=. \
--local dockerfile=.
buildctl build \
--frontend gateway.v0 \
--opt source=docker/dockerfile \
--opt context=https://github.com/moby/moby.git \
--opt build-arg:APT_MIRROR=cdn-fastly.deb.debian.org
输出
默认情况下,构建结果和中间缓存将仅保留在 BuildKit 内部。需要指定输出来检索结果。
图像/注册表
buildctl build ... --output type=image,name=docker.io/username/image,push=true
要将映像导出到多个注册表:
buildctl build ... --output type=image,\"name=docker.io/username/image,docker.io/username2/image2\",push=true
要导出与图像一起嵌入的缓存并将它们一起推送到注册表,registry需要键入导入缓存,您应该指定--export-cache type=inline和--import-cache type=registry,ref=...。如果要将缓存直接导出到本地,则应指定--export-cache type=local. 详细信息参见导出缓存。
buildctl build ...\
--output type=image,name=docker.io/username/image,push=true \
--export-cache type=inline \
--import-cache type=registry,ref=docker.io/username/image
图像输出支持的按键:
- name=<value>:指定图像名称
- push=true:创建镜像后推送
- push-by-digest=true: 推送未命名图像
- registry.insecure=true:推送到不安全的 HTTP 注册表
- oci-mediatypes=true:在配置 JSON 中使用 OCI 媒体类型而不是 Docker 的媒体类型
- unpack=true:创建后解压镜像(与containerd一起使用)
- dangling-name-prefix=<value>:用 命名图像prefix@<digest>,用于匿名图像
- name-canonical=true:添加额外的规范名称name@<digest>
- compression=<uncompressed|gzip|estargz|zstd>:为新创建和缓存的图层选择压缩类型,gzip 为默认值。etarz 应该与 一起使用oci-mediatypes=true。
- compression-level=<value>:gzip、estargz (0-9) 和 zstd (0-22) 的压缩级别
- force-compression=true:将compression选项强制应用于所有图层(包括已经存在的图层)
- store=true:将结果图像存储到工作人员(例如containerd)图像存储中,并确保图像在内容存储中具有所有blob(默认true)。如果工作人员没有图像存储(例如 OCI 工作人员),则忽略。
- annotation.<key>=<value>:将相应的注释附加key到value构建的图像上使用扩展语法annotation-<type>.<key>=<value>以及annotation[<platform>].<key>=<value>两者结合使用annotation-<type>[<platform>].<key>=<value>,可以准确配置附加注释的位置。<type>指定要附加到的对象,可以是manifest(默认)、manifest-descriptor和index中的任何一个index-descriptor<platform>指定要附加到哪些对象(默认情况下为所有对象),并且与传递到 opt 的密钥相同platform,请参阅docs/multi-platform.md。请参阅docs/annotations.md了解更多详情。
如果需要凭据,buildctl将尝试读取 Docker 配置文件$DOCKER_CONFIG/config.json。 $DOCKER_CONFIG默认为~/.docker.
本地目录
本地客户端会将文件直接复制到客户端。如果 BuildKit 用于构建容器镜像之外的其他内容,这非常有用。
buildctl build ... --output type=local,dest=path/to/output-dir
要导出特定文件,请使用带有临时阶段的多阶段构建,并将所需的文件复制到带有COPY --from.
...
FROM scratch as testresult
COPY --from=builder /usr/src/app/testresult.xml .
...
buildctl build ... --opt target=testresult --output type=local,dest=path/to/output-dir
通过多平台构建,将在目标目录中创建与每个目标平台匹配的子文件夹:
FROM busybox AS build
ARG TARGETOS
ARG TARGETARCH
RUN mkdir /out && echo foo > /out/hello-$TARGETOS-$TARGETARCH
FROM scratch
COPY --from=build /out /
$ buildctl build \
--frontend dockerfile.v0 \
--opt platform=linux/amd64,linux/arm64 \
--output type=local,dest=./bin/release
$ tree ./bin
./bin/
└── release
├── linux_amd64
│ └── hello-linux-amd64
└── linux_arm64
└── hello-linux-arm64
您可以设置platform-split=false将所有平台的文件合并到同一目录中:
$ buildctl build \
--frontend dockerfile.v0 \
--opt platform=linux/amd64,linux/arm64 \
--output type=local,dest=./bin/release,platform-split=false
$ tree ./bin
./bin/
└── release
├── hello-linux-amd64
└── hello-linux-arm64
Tar 导出器与本地导出器类似,但通过 tarball 传输文件。
buildctl build ... --output type=tar,dest=out.tar
buildctl build ... --output type=tar > out.tar
Docker 压缩包
# exported tarball is also compatible with OCI spec
buildctl build ... --output type=docker,name=myimage | docker load
OCI 压缩包
buildctl build ... --output type=oci,dest=path/to/output.tar
buildctl build ... --output type=oci > output.tar
容器镜像存储
需要使用containerdworker
buildctl build ... --output type=image,name=docker.io/username/image
ctr --namespace=buildkit images ls
要更改containerd命名空间,您需要worker.containerd.namespace更改/etc/buildkit/buildkitd.toml.
缓存
显示本地构建缓存 ( /var/lib/buildkit):
buildctl du -v
修剪本地构建缓存:
buildctl prune
垃圾收集
见./docs/buildkitd.toml.md。
导出缓存
BuildKit 支持以下缓存导出器:
- inline:将缓存嵌入到镜像中,并一起推送到注册表
- registry: 分别推送图片和缓存
- local:导出到本地目录
- gha:导出到 GitHub Actions 缓存
在大多数情况下,您想要使用inline缓存导出器。但请注意,inline缓存导出器仅支持min缓存模式。要启用max缓存模式,请使用缓存导出器分别推送图像和缓存registry。
inline和registry导出器都将缓存存储在注册表中。对于导入缓存,type=registry这对于两者来说都足够了,因为不需要指定缓存格式。
内联(将图像和缓存推送到一起)
buildctl build ... \
--output type=image,name=docker.io/username/image,push=true \
--export-cache type=inline \
--import-cache type=registry,ref=docker.io/username/image
请注意,除非提供内联缓存,否则不会导入内联缓存--import-cache type=registry,ref=...。
内联缓存将缓存元数据嵌入到图像配置中。与没有缓存信息的图像相比,图像中的图层将保持不变。
?? Docker 集成的 BuildKit ( DOCKER_BUILDKIT=1 docker build),docker buildx需要 --build-arg BUILDKIT_INLINE_CACHE=1指定才能启用inline缓存导出器。但是,独立版本buildctl不需要--opt build-arg:BUILDKIT_INLINE_CACHE=1,并且 build-arg 会被忽略。
注册表(分别推送镜像和缓存)
buildctl build ... \
--output type=image,name=localhost:5000/myrepo:image,push=true \
--export-cache type=registry,ref=localhost:5000/myrepo:buildcache \
--import-cache type=registry,ref=localhost:5000/myrepo:buildcache
--export-cache选项:
- type=registry
- mode=<min|max>:指定要导出的缓存层(默认:min)min:仅导出结果图像的图层max:导出所有中间步骤的所有层
- ref=<ref>:指定存储库引用来存储缓存,例如docker.io/user/image:tag
- image-manifest=<true|false>:是否将缓存清单导出为 OCI 兼容的图像清单而不是清单列表/索引(默认值:false,必须与 一起使用oci-mediatypes=true)
- oci-mediatypes=<true|false>:是否在导出的清单中使用 OCI 媒体类型(默认值:true,自 BuildKit 以来v0.8)
- compression=<uncompressed|gzip|estargz|zstd>:为新创建和缓存的图层选择压缩类型,gzip 为默认值。eargz 和 zstd 应该与oci-mediatypes=true
- compression-level=<value>:选择 gzip、estargz (0-9) 和 zstd (0-22) 的压缩级别
- force-compression=true:强制将compression选项应用于所有图层
- ignore-error=<false|true>:指定在缓存导出失败时是否忽略错误(默认值false:)
--import-cache选项:
- type=registry
- ref=<ref>:指定从中检索缓存的存储库引用,例如docker.io/user/image:tag
本地目录
buildctl build ... --export-cache type=local,dest=path/to/output-dir
buildctl build ... --import-cache type=local,src=path/to/input-dir
目录布局符合 OCI Image Spec v1.0。
--export-cache选项:
- type=local
- mode=<min|max>:指定要导出的缓存层(默认:min)min:仅导出结果图像的图层max:导出所有中间步骤的所有层
- dest=<path>:缓存导出器的目标目录
- tag=<tag>:指定图像的自定义标签写入本地索引(默认:latest)
- image-manifest=<true|false>:是否将缓存清单导出为 OCI 兼容的图像清单而不是清单列表/索引(默认值:false,必须与 一起使用oci-mediatypes=true)
- oci-mediatypes=<true|false>:是否在导出的清单中使用 OCI 媒体类型(默认true,自 BuildKit 以来v0.8)
- compression=<uncompressed|gzip|estargz|zstd>:为新创建和缓存的图层选择压缩类型,gzip 为默认值。eargz 和 zstd 应与 一起使用oci-mediatypes=true。
- compression-level=<value>:gzip、estargz (0-9) 和 zstd (0-22) 的压缩级别
- force-compression=true:强制将compression选项应用于所有图层
- ignore-error=<false|true>:指定在缓存导出失败时是否忽略错误(默认值false:)
--import-cache选项:
- type=local
- src=<path>:缓存导入器的源目录
- tag=<tag>:指定要从本地索引读取的图像的自定义标签(默认:latest)
- digest=sha256:<sha256digest>:指定要导入的清单列表的显式摘要
GitHub Actions 缓存(实验)
buildctl build ... \
--output type=image,name=docker.io/username/image,push=true \
--export-cache type=gha \
--import-cache type=gha
GitHub Actions 缓存将缓存元数据和图层保存到 GitHub 的缓存服务。该缓存目前的大小限制为 10GB,可在存储库中的不同缓存之间共享。如果超过此限制,GitHub 将保存您的缓存,但会开始逐出缓存,直到总大小小于 10 GB。过于频繁地回收缓存可能会导致整体运行时间变慢。
与使用actions/cache类似,缓存的范围是branch,每个分支都可以使用默认分支和目标分支。
需要以下属性来针对GitHub Actions Cache 服务 API进行身份验证:
- url:缓存服务器 URL(默认$ACTIONS_CACHE_URL)
- token:访问令牌(默认$ACTIONS_RUNTIME_TOKEN)
?? 这种类型的缓存可以与Docker Build Push Action where一起使用url,并且token会自动设置。要在内联run步骤中使用此后端,您必须在工作流程中包含mad-max/ghaction-github-runtime 以公开运行时。
--export-cache选项:
- type=gha
- mode=<min|max>:指定要导出的缓存层(默认:min)min:仅导出结果图像的图层max:导出所有中间步骤的所有层
- scope=<scope>:缓存对象属于哪个范围(默认buildkit)
- ignore-error=<false|true>:指定在缓存导出失败时是否忽略错误(默认值false:)
--import-cache选项:
- type=gha
- scope=<scope>:缓存对象属于哪个范围(默认buildkit)
S3 缓存(实验性)
buildctl build ... \
--output type=image,name=docker.io/username/image,push=true \
--export-cache type=s3,region=eu-west-1,bucket=my_bucket,name=my_image \
--import-cache type=s3,region=eu-west-1,bucket=my_bucket,name=my_image
需要以下属性:
- bucket:AWS S3 存储桶(默认值$AWS_BUCKET:)
- region:AWS 区域(默认:$AWS_REGION)
储存地点:
- 斑点:s3://<bucket>/<prefix><blobs_prefix>/<sha256>,默认值:s3://<bucket>/blobs/<sha256>
- 清单:s3://<bucket>/<prefix><manifests_prefix>/<name>,默认:s3://<bucket>/manifests/<name>
S3配置:
- blobs_prefix:在 s3 上存储/读取 blob 的全局前缀(默认值blobs/:)
- manifests_prefix:在 s3 上存储/读取清单的全局前缀(默认值manifests/:)
- endpoint_url:指定特定的S3端点(默认:空)
- use_path_style:如果设置为true,则将存储桶名称放在 URL 中而不是主机名中(默认值:false)
AWS 身份验证:
最简单的方法是使用 IAM 实例配置文件。其他选项有:
- 使用AWS Go SDK支持的环境变量/配置文件的任何系统。该配置必须可用于 buildkit 守护进程,而不是客户端。
- 使用以下属性:access_key_id:访问密钥 IDsecret_access_key:秘密访问密钥session_token:会话令牌
--export-cache选项:
- type=s3
- mode=<min|max>:指定要导出的缓存层(默认:min)min:仅导出结果图像的图层max:导出所有中间步骤的所有层
- prefix=<prefix>:设置全局前缀以在 s3 上存储/读取文件(默认:空)
- name=<manifest>:指定要使用的清单名称(默认buildkit)可以同时指定多个清单名称,以 分隔;。标准用例是使用 git sha1 作为名称,使用分支名称作为重复名称,并使用 2 个import-cache命令加载两者。
- ignore-error=<false|true>:指定在缓存导出失败时是否忽略错误(默认值false:)
--import-cache选项:
- type=s3
- prefix=<prefix>:设置全局前缀以在 s3 上存储/读取文件(默认:空)
- blobs_prefix=<prefix>:设置全局前缀以在 s3 上存储/读取 blob(默认值blobs/:)
- manifests_prefix=<prefix>:设置全局前缀以在 s3 上存储/读取清单(默认值manifests/:)
- name=<manifest>:要使用的清单名称(默认buildkit)
Azure Blob 存储缓存(实验性)
buildctl build ... \
--output type=image,name=docker.io/username/image,push=true \
--export-cache type=azblob,account_url=https://myaccount.blob.core.windows.net,name=my_image \
--import-cache type=azblob,account_url=https://myaccount.blob.core.windows.net,name=my_image
需要以下属性:
- account_url:Azure Blob 存储帐户 URL(默认值$BUILDKIT_AZURE_STORAGE_ACCOUNT_URL:)
储存地点:
- 斑点:<account_url>/<container>/<prefix><blobs_prefix>/<sha256>,默认值:<account_url>/<container>/blobs/<sha256>
- 清单:<account_url>/<container>/<prefix><manifests_prefix>/<name>,默认:<account_url>/<container>/manifests/<name>
Azure Blob 存储配置:
- container:Azure Blob 存储容器名称(默认值:buildkit-cache或$BUILDKIT_AZURE_STORAGE_CONTAINER如果设置)
- blobs_prefix:在 Azure Blob 存储容器上存储/读取 Blob 的全局前缀 ( <container>)(默认值:blobs/)
- manifests_prefix:在 Azure Blob 存储容器上存储/读取 Blob 的全局前缀 ( <container>)(默认值:manifests/)
Azure Blob 存储身份验证:
Azure Blob 存储身份验证支持 2 个选项:
- 使用Azure SDK for Go支持的环境变量的任何系统。该配置必须可用于 buildkit 守护进程,而不是客户端。
- 秘密访问密钥,使用该secret_access_key属性指定 Azure Blob 存储帐户的主要或辅助帐户密钥。Azure Blob 存储帐户密钥
Note
如果帐户名称不是帐户 URL 主机的一部分,也可以使用account_name属性(或)指定帐户名称。$BUILDKIT_AZURE_STORAGE_ACCOUNT_NAME
--export-cache选项:
- type=azblob
- mode=<min|max>:指定要导出的缓存层(默认:min)min:仅导出结果图像的图层max:导出所有中间步骤的所有层
- prefix=<prefix>:设置全局前缀以在 Azure Blob 存储容器上存储/读取文件 ( <container>)(默认值:空)
- name=<manifest>:指定要使用的清单名称(默认值buildkit:)可以同时指定多个清单名称,以 分隔;。标准用例是使用 git sha1 作为名称,使用分支名称作为重复名称,并使用 2 个import-cache命令加载两者。
- ignore-error=<false|true>:指定在缓存导出失败时是否忽略错误(默认值false:)
--import-cache选项:
- type=azblob
- prefix=<prefix>:设置全局前缀以在 Azure Blob 存储容器上存储/读取文件 ( <container>)(默认值:空)
- blobs_prefix=<prefix>:设置全局前缀以在 Azure Blob 存储容器上存储/读取 Blob ( <container>)(默认值:blobs/)
- manifests_prefix=<prefix>:设置全局前缀以在 Azure Blob 存储容器上存储/读取清单 ( <container>)(默认值:manifests/)
- name=<manifest>:要使用的清单名称(默认值buildkit:)
一致性哈希
如果您有多个 BuildKit 守护程序实例,但不想使用注册表在集群中共享缓存,请考虑使用一致哈希进行客户端负载平衡。
见./examples/kubernetes/consistenthash。
元数据
要输出构建元数据(例如图像摘要),请传递该--metadata-file标志。元数据将作为 JSON 对象写入指定文件。指定文件的目录必须已存在且可写。
buildctl build ... --metadata-file metadata.json
jq '.' metadata.json
{
"containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"containerimage.descriptor": {
"annotations": {
"config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"org.opencontainers.image.created": "2022-02-08T21:28:03Z"
},
"digest": "sha256:19ffeab6f8bc9293ac2c3fdf94ebe28396254c993aea0b5a542cfb02e0883fa3",
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 506
},
"containerimage.digest": "sha256:19ffeab6f8bc9293ac2c3fdf94ebe28396254c993aea0b5a542cfb02e0883fa3"
}
Systemd 套接字激活
在基于 Systemd 的系统上,您可以通过Systemd 套接字激活、使用 与守护进程通信buildkitd --addr fd://。您可以在 中找到通过 BuildKit 和 Systemd 使用 Systemd 套接字激活的示例./examples/systemd。
将 BuildKit 公开为 TCP 服务
该buildkitd守护进程可以侦听 TCP 套接字上的 gRPC API。
强烈建议为守护程序和客户端 (mTLS) 创建 TLS 证书。在没有 mTLS 的情况下启用 TCP 是危险的,因为执行器容器(也称为 DockerfileRUN容器)也可以调用 BuildKit API。
buildkitd \
--addr tcp://0.0.0.0:1234 \
--tlscacert /path/to/ca.pem \
--tlscert /path/to/cert.pem \
--tlskey /path/to/key.pem
buildctl \
--addr tcp://example.com:1234 \
--tlscacert /path/to/ca.pem \
--tlscert /path/to/clientcert.pem \
--tlskey /path/to/clientkey.pem \
build ...
负载均衡
buildctl build可以针对随机负载平衡的守护buildkitd进程进行调用。
另请参阅客户端负载平衡的一致性哈希。
容器化 BuildKit
还可以通过buildkitd在 Docker 容器内运行守护程序并远程访问它来使用 BuildKit。
我们提供的容器镜像如下moby/buildkit:
- moby/buildkit:latest:从最新的常规版本构建
- moby/buildkit:rootless:与非特权用户相同,latest但以非特权用户身份运行,请参阅docs/rootless.md
- moby/buildkit:master:从 master 分支构建
- moby/buildkit:master-rootless:与 master 相同,但以非特权用户身份运行,请参阅docs/rootless.md
要在容器中运行守护进程:
docker run -d --name buildkitd --privileged moby/buildkit:latest
export BUILDKIT_HOST=docker-container://buildkitd
buildctl build --help
Podman
要连接到 Podman 容器中运行的 BuildKit 守护进程,请podman-container://使用docker-container://.
podman run -d --name buildkitd --privileged moby/buildkit:latest
buildctl --addr=podman-container://buildkitd build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=oci | podman load foo
sudo不需要。
Nerdctl
要连接到在 Nerdctl 容器中运行的 BuildKit 守护进程,请nerdctl-container://使用docker-container://.
nerdctl run -d --name buildkitd --privileged moby/buildkit:latest
buildctl --addr=nerdctl-container://buildkitd build --frontend dockerfile.v0 --local context=. --local dockerfile=. --output type=oci | nerdctl load
sudo不需要。
Kubernetes
对于 Kubernetes 部署,请参阅examples/kubernetes。
无守护进程
要在单个容器中运行客户端和临时守护进程(“无守护进程模式”):
docker run \
-it \
--rm \
--privileged \
-v /path/to/dir:/tmp/work \
--entrypoint buildctl-daemonless.sh \
moby/buildkit:master \
build \
--frontend dockerfile.v0 \
--local context=/tmp/work \
--local dockerfile=/tmp/work
或者
docker run \
-it \
--rm \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
-e BUILDKITD_FLAGS=--oci-worker-no-process-sandbox \
-v /path/to/dir:/tmp/work \
--entrypoint buildctl-daemonless.sh \
moby/buildkit:master-rootless \
build \
--frontend \
dockerfile.v0 \
--local context=/tmp/work \
--local dockerfile=/tmp/work
OpenTelemetry support
BuildKit 支持buildkitd gRPC API 和 buildctl 命令的OpenTelemetry 。要捕获Jaeger的跟踪 ,请将JAEGER_TRACE 环境变量设置为收集地址。
docker run -d -p6831:6831/udp -p16686:16686 jaegertracing/all-in-one:latest
export JAEGER_TRACE=0.0.0.0:6831
# restart buildkitd and buildctl so they know JAEGER_TRACE
# any buildctl command should be traced to http://127.0.0.1:16686/
在没有 root 权限的情况下运行 BuildKit
请参考docs/rootless.md。
项目地址:https://github.com/moby/buildkit