多平台镜像
方式一:通过清单文件构建多平台镜像
不同平台镜像通过在 tag 标签带上一个后缀标识这个平台,将多个平台的镜像推送到镜像仓库,然后通过 docker 的清单列表功能将多个 tag 合并为一个,然后推送这个清单文件到镜像仓库
# 在 arm64 的机器上构建 arm64 的镜像
docker build -t xxx:1.0.0-arm64 .
docker push xxx:xxx-arm64
# 在 amd64 的机器上构建 amd64 的镜像
docker build -t xxx:xxx-amd64 .
docker push xxx:1.0.0-amd64
# 在任意机器上,创建清单列表将两个平台的镜像放到一个 tag 下
docker manifest create xxx:1.0.0 \
-a xxx:1.0.0-arm64 \
-a xxx:1.0.0-amd64
# 推送清单列表到镜像仓库
docker manifest push xxx:1.0.0
之后可以通过 docker pull xxx:1.0.0
的方式拉取镜像,镜像仓库会自动区分平台
manifest 功能需要镜像仓库开启 https,docker 为镜像配置的 http 不会生效。
方式二:通过 docker buildx
交叉编译得到多平台镜像
github buildx | buildx 安装使用 buildkitd.toml.md | buildx 配置文件 buildx 需要 linux 内核支持:内核 >= 4.8 (
uname -a
查看内核版本) 和 binfmt-support >= 2.1.7
安装 tonistiigi/binfmt
docker run --privileged --rm tonistiigi/binfmt --install all
# 查看本机支持的编译平台:
# cat /proc/sys/fs/binfmt_misc/qemu-*
为 buildx 创建一个新的编译器实例(默认实例不支持指定多个编译平台)
docker buildx create --use --name mybuilder
# 创建自定义编译器时指定 buildit 配置文件
# docker buildx create --use --name mybuilder --config xxx.toml
如果要通过 http 或者自签证书的 https 从镜像仓库拉取/推送镜像,需要在创建 编译器实例时通过
--config
指定 buildkit 配置文件:详情查看:buildkitd.toml.md
启动构建器
docker buildx inspect mybuilder --bootstrap
# 查看构建器支持的平台
# docker buildx ls
通过 --platform
参数指定要构建哪些平台的镜像
docker buildx build --load --platform linux/amd64,linux/arm64 -t xxx:1.0.0 .
可通过
docker pull xxx:1.0.0 --platform linux/arm64
拉取不同平台的镜像 配置了 buildx 后可直接跨平台运行支持的镜像 使用--provenance=false
参数,不然生成的平台镜像会多一个 unknown/unknown,见:https://github.com/docker/buildx/issues/1964#issuecomment-1644634461
默认情况下构建出来的镜像只保存在缓存中,本地 docker images 命令查看不到。可以通过增加如下选项:
--load
:加载到本地的 Docker 镜像列表中(仅支持指定一个平台架构)--output
:保存为本地文件(仅支持指定一个平台架构)--push
:在构建完成后自动将清单文件推送到镜像仓库
--output
保存到本地文件示范:
docker buildx build --platform linux/arm64 --output type=docker,dest=xxx_1.0.0_arm64.tar -t xxx:1.0.0 .
type
选项
type
定义了输出的类型,可以是以下几种之一:
-
type=docker
:- 将镜像导出为可以通过
docker load
加载的 Docker 镜像文件(*.tar
)。 - 相关的配置:
dest
:指定文件保存的路径(例如output.tar
)。
示例:
- 将镜像导出为可以通过
docker buildx build --output type=docker,dest=output_image.tar -t your_image_name:tag .
-
type=oci
:- 将镜像导出为 OCI 格式的镜像文件,符合 OCI(Open Container Initiative)标准。
- 相关的配置:
dest
:指定文件保存的路径。
示例:
docker buildx build --output type=oci,dest=output_image.tar -t your_image_name:tag .
-
type=local
:- 将镜像文件系统导出到本地文件系统目录中,而不是一个单一的镜像文件。适用于将构建结果导出为一个普通的文件结构。
- 相关的配置:
dest
:指定输出目录的路径。
示例:
docker buildx build --output type=local,dest=./output_directory -t your_image_name:tag .
-
type=tar
:- 将镜像导出为 tar 文件,但与
type=docker
不同的是,type=tar
导出的是镜像文件系统,而不是完整的 Docker 镜像。 - 相关的配置:
dest
:指定保存 tar 文件的路径。
示例:
- 将镜像导出为 tar 文件,但与
docker buildx build --output type=tar,dest=output_filesystem.tar -t your_image_name:tag .
-
type=registry
:- 将镜像推送到指定的容器镜像仓库(如 Docker Hub、私有仓库)。
- 无需指定
dest
参数,因为输出目标是远程仓库。 - 你可以指定仓库和标签名称。
示例:
docker buildx build --output type=registry -t your_registry/your_image_name:tag .
-
type=image
(需要 Docker 20.10.7+):- 用于将镜像直接保存到本地的 Docker 实例中,类似于
--load
的效果,但提供了更多选项。 - 相关的配置:
name
:指定镜像名称。push
:是否将镜像推送到远程仓库。
示例:
- 用于将镜像直接保存到本地的 Docker 实例中,类似于
docker buildx build --output type=image,name=your_image_name:tag,push=false -t your_image_name:tag .
如果执行过程中报错:
libc-bin segfaults ( script subprocess returned error exit status 139 ) ( qemu: uncaught target signal 11 (Segmentation fault) - core dumped )
见:https://github.com/docker/buildx/issues/314 讨论
执行如下操作可修复:
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -c yes