- 所有文章/
构建支持多种 CPU 架构的 Docker 镜像
本文目录
前言 #
最近甲骨文首尔 ARM 免费服务器大量放货,我也开了一台 4C 24GB 的机器。这么大内存的机器,我想要在上面托管一些项目,由于一些项目的 Docker 镜像未提供 ARM 架构的支持,所以我了解了一下使用 Docker Buildx 来构建支持多架构的 Docker 镜像。
Docker Buildx 是 Docker CLI 的一个插件,它是默认 Docker Build 命令的拓展,完全支持 Moby BuildKit 构建器的特性并提供与 Docker Build 一致的体验,它带来的新特性之一就是支持构建多架构镜像,更多信息可以查看 Docker 文档 - Docker Buildx。
在构建机器上构建与本机 CPU 架构不同的 Docker 镜像会用到 QEMU 的用户空间 (userspace) 仿真和虚拟化,由于虚拟化和模拟有一定性能损失,所以整个构建过程会花费更多时间。
本文不讨论 Dockerfile 的写法,我们以 book-searcher 项目为例,在甲骨文 ARM 服务器 1 上构建支持 AMD64, ARM/V7, ARM64 的 Docker 镜像并推送到 Docker Hub
uname -a
Linux instance-oracle-arm 5.10.0-20-arm64 #1 SMP Debian 5.10.158-2 (2022-12-13) aarch64 GNU/Linux
准备 #
Docker Buildx 在 Docker 19.03 以上版本默认支持,在开始前,建议将构建机器上的 Docker 升级到最新版本
# 查看 buildx 版本信息
sudo docker buildx version
github.com/docker/buildx v0.10.0-docker 876462897612d36679153c3414f7689626251501
# 命令帮助
sudo docker buildx
Usage: docker buildx [OPTIONS] COMMAND
Extended build capabilities with BuildKit
Options:
--builder string Override the configured builder instance
Management Commands:
imagetools Commands to work on images in registry
Commands:
bake Build from a file
build Start a build
create Create a new builder instance
du Disk usage
inspect Inspect current builder instance
ls List builder instances
prune Remove build cache
rm Remove a builder instance
stop Stop builder instance
use Set the current builder instance
version Show buildx version information
Run 'docker buildx COMMAND --help' for more information on a command.
tonistiigi/binfmt 是一使用 Docker 镜像分发的跨平台仿真模拟器集合,在 Windows/macOS 上的 Docker Desktop 一般默认已经安装了
# 安装所有 CPU 架构模拟器
sudo docker run --privileged --rm tonistiigi/binfmt --install all
# 安装指定 CPU 架构模拟器
sudo docker run --privileged --rm tonistiigi/binfmt --install arm64,riscv64,arm
在 Linux 机器上安装
sudo docker run --privileged --rm tonistiigi/binfmt --install all
Unable to find image 'tonistiigi/binfmt:latest' locally
latest: Pulling from tonistiigi/binfmt
6dda554f4baf: Pull complete
2b0720d7a501: Pull complete
Digest: sha256:66e11bea77a5ea9d6f0fe79b57cd2b189b5d15b93a2bdb925be22949232e4e55
Status: Downloaded newer image for tonistiigi/binfmt:latest
{
"supported": [
"linux/arm64",
"linux/amd64",
"linux/riscv64",
"linux/ppc64le",
"linux/s390x",
"linux/386",
"linux/mips64le",
"linux/mips64",
"linux/arm/v7",
"linux/arm/v6"
],
"emulators": [
"qemu-i386",
"qemu-mips64",
"qemu-mips64el",
"qemu-ppc64le",
"qemu-riscv64",
"qemu-s390x",
"qemu-x86_64"
]
}
前面也提到这个构建过程一般会花费更多时间,我们可以使用 screen 来保证会话不会中断 2
# Debian/Ubuntu 安装
sudo apt install -y screen
# 新建一个名为 build 的会话
screen -S build
# 列出开启的 screen 会话
screen -ls
# 恢复某个 screen 会话(比如,上面的 build)
screen -r build
在 Docker Hub 创建一个仓库,创建一个登录令牌用于登录
sudo docker login -u [username]
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
创建一个名称为 multiarch 的 buildx 构建实例并立即使用
sudo docker buildx create --name multiarch --use
列出所有的 buildx 构建实例状态,可以看到这个新的 buildx 构建实例还未启动
sudo docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
multiarch * docker-container
multiarch0 unix:///var/run/docker.sock inactive
default docker
default default running 20.10.22 linux/arm64, linux/arm/v7, linux/arm/v6, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386
我们可以立即启动这个构建实例(不是必须的)
sudo docker buildx inspect --bootstrap
Name: multiarch
Driver: docker-container
Nodes:
Name: multiarch0
Endpoint: unix:///var/run/docker.sock
Status: running
Buildkit: v0.11.0
Platforms: linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
再次查看所有 buildx 构建实例状态,可以看到已经在运行了
sudo docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
multiarch * docker-container
multiarch0 unix:///var/run/docker.sock running v0.11.0 linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default docker
default default running 20.10.22 linux/arm64, linux/arm/v7, linux/arm/v6, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386
开始 #
现在可以开始构建多架构的 Docker 镜像了,以 book-searcher 为例
# 拉取 book-searcher 源码
git clone https://github.com/book-searcher-org/book-searcher.git
cd book-searcher
# 开始构建并推送到 Docker Hub 仓库(注意替换 dejavumoe/book-searcher:0.8.3)
sudo docker buildx build -t dejavumoe/book-searcher:0.8.3 --platform=linux/arm/v7,linux/arm64,linux/amd64 . --push
开始构建过程
构建成功后,镜像会推送到 Docker Hub,比如文中示例的 book-searcher。
清理 #
镜像构建并推送完成后,如果没有特殊需求,可以删除构建缓存
# 查看 buildx 构建缓存
sudo docker buildx du
ID RECLAIMABLE SIZE LAST ACCESSED
no7ihggdz0dg9w916xfqdgpo4* true 1.649GB 19 hours ago
zfsooeun4nk9wuuhzkbs13bvg* true 1.631GB 19 hours ago
17luobonj5ah02zvbvvjemxhr true 981.7MB 19 hours ago
...
9kdh9ldirubp6ulj6h5anjsrn* true 8.192kB 19 hours ago
Reclaimable: 14.79GB
Total: 14.79GB
# 删除 buildx 构建缓存
sudo docker buildx prune
也可以删除 buildx 实例
sudo docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
multiarch * docker-container
multiarch0 unix:///var/run/docker.sock running v0.11.0 linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default docker
default default running 20.10.22 linux/arm64, linux/arm/v7, linux/arm/v6, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386
# 停止 buildx 实例
sudo docker buildx stop multiarch
# 删除 buildx 实例
sudo docker buildx rm multiarch
如果构建 Dockerfile 中的基础镜像不支持某些特定的 CPU 架构、某些项目缺少特定的的链接库……等原因会导致镜像构建失败,这就不在本文讨论范畴之内了 😂。
参考信息