什么是 docker buildx
Docker Buildx是一个CLI插件,它扩展了Docker命令,完全支持Moby BuildKit builder toolkit提供的功能。它提供了与docker build相同的用户体验,并提供了许多新功能,如创建作用域生成器实例和针对多个节点并发构建。
Docker Buildx包含在Docker 19.03中,并与以下Docker Desktop版本捆绑在一起。请注意,必须启用“实验特性”选项才能使用Docker Buildx。
Docker Desktop Enterprise version 2.1.0
Docker Desktop Edge version 2.0.4.0 or higher
创建 builder 实例
由于 Docker 默认的 builder 实例不支持同时指定多个 –platform,所有我们必须先创建一个 builder 实例
$ docker buildx create --use --name=mybuilder-cn --driver docker-container
--use
表示使用当前创建的 builder 实例--name
实例名称--driver
实例驱动(docker、 docker-container 和 kubernetes)
更多用法通过命令 docker buildx create -h
查看
查看新实例
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS mybuilder-cn * docker-container mybuilder-cn0 unix:///var/run/docker.sock inactive default docker default default running linux/amd64, linux/386
其中 * 表示当前正在使用的builder实例。
我们查看一下实例详细信息
docker buildx inspect Name: mybuilder-cn Driver: docker-container Nodes: Name: mybuilder-cn0 Endpoint: unix:///var/run/docker.sock Status: running Platforms: linux/amd64, linux/386
构建镜像
- 创建Dockerfile 文件
FROM --platform=$TARGETPLATFORM alpine RUN uname -a > /os.txt CMD cat /os.txt
这里使用到了变量 TARGETPLATFORM, 内置的一些变量在本文下方了解
- 使用 docker buildx build 命令构建镜像
构建指定平台
最简单的方法
$ docker buildx build . WARN[0000] No output specified for docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load [+] Building 32.9s (6/6) FINISHED => [internal] booting buildkit 25.4s => => pulling image moby/buildkit:buildx-stable-1 23.9s => => creating container buildx_buildkit_mybuilder-cn0 1.5s => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 115B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for docker.io/library/alpine:latest 5.1s => [1/2] FROM docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 1.9s => => resolve docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => => sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e 2.81MB / 2.81MB 1.8s => => extracting sha256:a0d0a0d46f8b52473982a3c466318f479767577551a53ffc9074c9fa7035982e 0.1s => [2/2] RUN uname -a > /os.txt
从上面的输出可以看出,构建步骤大概如下:
- 加载引导buildkit
- 下载镜像文件 image moby/buildkit:buildx-stable-1
- 使用镜像创建容器 buildx_buildkit_mybuilder-cn0
- 将当前 Dockerfile 文件传输到容器内
- 在容器内下载镜像 docker.io/library/alpine:latest
- 运行Dockerfile中的 RUN 指令
如果你用 docker ps 命令查看容器的话,会看到创建了一个 buildkitd 容器
构建多平台镜像
也可以指定一些设置,如构建的目标平台等
$ docker buildx build --platform linux/arm,linux/arm64,linux/amd64 -t cfanbo/hello . --push [+] Building 18.4s (18/18) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 115B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [linux/amd64 internal] load metadata for docker.io/library/alpine:latest 2.3s => [linux/arm64 internal] load metadata for docker.io/library/alpine:latest 2.4s => [linux/arm/v7 internal] load metadata for docker.io/library/alpine:latest 2.7s => [auth] library/alpine:pull token for registry-1.docker.io 0.0s => [auth] library/alpine:pull token for registry-1.docker.io 0.0s => [auth] library/alpine:pull token for registry-1.docker.io 0.0s => [linux/arm/v7 1/2] FROM docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => => resolve docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => [linux/arm64 1/2] FROM docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => => resolve docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => [linux/amd64 1/2] FROM docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => => resolve docker.io/library/alpine@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s => CACHED [linux/arm/v7 2/2] RUN uname -a > /os.txt 0.0s => CACHED [linux/arm64 2/2] RUN uname -a > /os.txt 0.0s => CACHED [linux/amd64 2/2] RUN uname -a > /os.txt 0.0s => exporting to image 15.5s => => exporting layers 0.0s => => exporting manifest sha256:fc3842a7caa48e4124d6a76dcb1cff3944e55eeefd5daeb21dfe8201de8d856c 0.0s => => exporting config sha256:4db341c87f5e347b12f2f8955da60ac4db9bcf2bc17aed18079d2ac55b759cca 0.0s => => exporting manifest sha256:91bcf398194707f1b9ce9fe6b7dcc29b809dc3278cddc1a13cb5dc76d60bb281 0.0s => => exporting config sha256:e0f919da8544b23e919c1257c6b40c54a4c9114447e1d637f4d965204757dbab 0.0s => => exporting manifest sha256:4a5479758b57441933984c2209bccff4f0c47c7dd74be95b4b22162d105e639a 0.0s => => exporting config sha256:6af666ad21adae02a9147dfcec4c9397e2be9e12d5861614e5fc20a287fe4086 0.0s => => exporting manifest list sha256:e8758d75c4d6cf2a633c645616c1d4f76006ee0503d7b16532a744346bca0cf7 0.0s => => pushing layers 12.4s => => pushing manifest for docker.io/cfanbo/hello:latest@sha256:e8758d75c4d6cf2a633c645616c1d4f76006ee0503d7b16532a744346bca0cf7 3.1s => [auth] cfanbo/hello:pull,push token for registry-1.docker.io 0.0s => [auth] cfanbo/hello:pull,push token for registry-1.docker.io 0.0s => [auth] cfanbo/hello:pull,push token for registry-1.docker.io
这里我们指定了三个平台,它们将同时分别进行构建。由于我这里多次执行了构建命令,所以三个平台构建过程中都显示 CACHED,表示用到了缓存。
我这里 https://hub.docker.com 平台的用户名为 cfanbo, 替换为自己的 Docker Hub 用户名。
--push
参数表示将构建好的镜像推送到 Docker 仓库,在构建前记得先执行 docker login 命令登录。这里通过 https://hub.docker.com/repository/docker/cfanbo/hello/tags?page=1&ordering=last_updated 可以看到分别为三个平台构建了不同的镜像。
- 查看镜像信息
$ docker buildx imagetools inspect cfanbo/hello Name: docker.io/cfanbo/hello:latest MediaType: application/vnd.docker.distribution.manifest.list.v2+json Digest: sha256:e8758d75c4d6cf2a633c645616c1d4f76006ee0503d7b16532a744346bca0cf7 Manifests: Name: docker.io/cfanbo/hello:latest@sha256:fc3842a7caa48e4124d6a76dcb1cff3944e55eeefd5daeb21dfe8201de8d856c MediaType: application/vnd.docker.distribution.manifest.v2+json Platform: linux/arm/v7 Name: docker.io/cfanbo/hello:latest@sha256:91bcf398194707f1b9ce9fe6b7dcc29b809dc3278cddc1a13cb5dc76d60bb281 MediaType: application/vnd.docker.distribution.manifest.v2+json Platform: linux/arm64 Name: docker.io/cfanbo/hello:latest@sha256:4a5479758b57441933984c2209bccff4f0c47c7dd74be95b4b22162d105e639a MediaType: application/vnd.docker.distribution.manifest.v2+json Platform: linux/amd64
- 验证镜像
### Linux $ docker run --rm cfanbo/hello:latest Linux buildkitsandbox 5.11.0-31-generic #33-Ubuntu SMP Wed Aug 11 13:19:04 UTC 2021 x86_64 Linux ### aarch64 $ sudo docker run --rm cfanbo/hello:latest Linux buildkitsandbox 5.11.0-31-generic #33-Ubuntu SMP Wed Aug 11 13:19:04 UTC 2021 aarch64 Linux
常量
Dockerfile 支持如下架构相关的变量
TARGETPLATFORM
构建镜像的目标平台,例如 linux/amd64, linux/arm/v7, windows/amd64。
TARGETOS
构建镜像目标平台的 OS 类型,例如 linux, windows
TARGETARCH
构建镜像目标平台的架构类型,例如 amd64, arm
TARGETVARIANT
构建镜像目标平台的变种,该变量可能为空,例如 v7
BUILDPLATFORM
构建镜像所使用的主机平台,例如 linux/amd64
BUILDOS
构建镜像所使用主机平台 的 OS 类型,例如 linux
BUILDARCH
构建镜像所使用主机平台 的架构类型,例如 amd64
BUILDVARIANT
构建镜像所使用主机平台 的变种,该变量可能为空,例如 v7
使用举例
例如我们要构建支持 linux/arm/v7 和 linux/amd64 两种架构的镜像。假设已经生成了两个平台对应的二进制文件:
bin/dist-linux-arm bin/dist-linux-amd64
那么 Dockerfile 可以这样书写:
FROM scratch # 使用变量必须申明 ARG TARGETOS ARG TARGETARCH COPY bin/dist-${TARGETOS}-${TARGETARCH} /dist ENTRYPOINT ["dist"]