Appearance
Docker异构镜像
配置Docker buildx环境
1、确保 Docker 版本不低于 19.03,才能使用 buildx
docker --version2、检查 buildx 插件
docker buildx version通过apt或者yum等包管理方式安装的Docker,默认是带有 buildx 插件的
如果使用的 Docker 版本中没有包含 buildx,或者想要安装最新版本的 buildx,可以访问 github - docker/buildx 获取安装指南
3、安装 buildx 插件
bash
wget https://github.com/docker/buildx/releases/download/v0.14.0/buildx-v0.14.0.linux-amd64
chmod a+x buildx-v0.14.0.linux-amd64
mkdir -p /usr/libexec/docker/cli-plugins
mv buildx-v0.14.0.linux-amd64 /usr/libexec/docker/cli-plugins/docker-buildx4、启用实验性功能
为了构建多平台镜像,需要确保 Docker 的实验性功能被启用,因为 buildx 依赖这些功能。 通过修改 Docker 配置文件(通常位于 /etc/docker/daemon.json)来启用实验功能。
bash
vi /etc/docker/daemon.json
# 追加填入以下内容,确保json格式正确
{
"experimental": true
}5、执行以下命令
bash
systemctl daemon-reload
systemctl restart docker6、查看是否开启实验特性以及是否安装成功buildx
bash
docker version --format '{{.Server.Experimental}}'
# 如果结果为true则实验特性已经开启
docker buildx version7、成功安装完成buildx插件之后需要创建
bash
#正常创建方式
docker buildx create --name image_buildx --use
#添加代理方式,docker buildx插件和docker的代理不通用,如果需要拉取docker hub的镜像,需要添加为自己的代理端口
docker buildx create --name image_buildx --driver-opt env.http_proxy=127.0.0.1:7890 --driver-opt env.https_proxy=127.0.0.1:7890 --use8、接下来就可以在x86平台构造arm的docker镜像了
bash
docker buildx build \
--platform linux/arm64 \
--tag ${IMAGE_TAG} \
-f Dockerfile \
--load \
.构建过程会用到镜像:
moby/buildkit:buildx-stable-1
9、直接在X86架构的机器上运行构建好的ARM64镜像是不可能的,因为不同架构的机器无法直接执行其他架构的二进制代码。ARM64镜像包含的是为ARM处理器编译的代码,而X86架构的CPU无法理解这些指令。 在x86上运行arm架构的镜像需要使用QEMU仿真
确保docker实验特性已经开启
bash
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes仿真开启成功后就可以使用arm镜像了,使用方式如下:
bash
docker run -it --platform=linux/arm64 your-arm64-image多架构镜像
通过 Single Repository 的方式,提供不同架构的镜像
Docker Manifest
Docker 提供了 Docker Manifest 来解决跨平台镜像构建的问题,它是一种用于描述不同 CPU 架构、操作系统和操作系统版本的多平台 Docker 镜像的格式。
可以将不同平台的镜像打包成一个 Image Manifests,并将其上传到 镜像仓库。
Manifest list 为不同的架构指向不同的镜像,当在特定的架构上使用镜像时,Docker 会快速检测与当前平台兼容的镜像版本,并且自动从镜像仓库中下载相应的镜像。
这样使得在不同的架构上运行 Docker 容器时更加的方便和灵活,而且多架构镜像本身也是遵循 Build Once, Deploy Anywhere 的原则。
查看一个多架构镜像的 Manifest
docker manifest inspect harbor.liulike.top/amd/open-euler:20.03-lts-sp3{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 528,
"digest": "sha256:c3f469382b523084d9fa7a7599a11740d1156201bab3f732ec95059d998f32f7",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 528,
"digest": "sha256:97b8a8d81913535dedd64a0a316aaccaa540334c46a0c3f92775a19f0d9478a9",
"platform": {
"architecture": "arm64",
"os": "linux"
}
}
]
}在输出中,可以看到 ghcr.io/lqshow/multi-arch-build/app-2:v0.0.1 的 Manifest 包含了一个 manifest list,正因为如此,当用户在不同平台上拉取该镜像时,Docker 会自动根据当前系统架构和操作系统版本来选择并下载相应的镜像层。
两者的 mediaType 是不同的,它们其实是不同的标准和实现: 一个是 Docker Media Type 定义:application/vnd.docker.distribution.manifest.v2+json 另外一个是 OCI Media Type 定义:application/vnd.oci.image.index.v1+json
那么 OCI Media Types 和 Docker Media Types 的区别是什么?以下是 ChatGPT 给出的答案:
OCI Media Types:
它是 Open Container Initiative 的规范,用于定义容器镜像的格式和组成,包括镜像索引、镜像配置和镜像层等。这些媒体类型通常以 "application/vnd.oci.image." 开头,例如
application/vnd.oci.image.manifest.v1+json。Docker Media Types:
它是 Docker 镜像格式的一部分,用于定义 Docker 容器镜像的格式和组成,包括镜像索引、镜像配置和镜像层等。这些媒体类型通常以 "application/vnd.docker." 开头,例如
application/vnd.docker.distribution.manifest.v2+json。两者之间的区别在于 OCI 是一个通用容器规范,可以和其他容器运行时协作使用,而 Docker 是基于 Docker 引擎的容器规范,主要用于 Docker 专用容器运行时的操作。
关于 OCI Media Types 和 Docker Media Types 的更多信息,请参阅以下链接:
- OCI Media Types: **https://github.com/opencontainers/image-spec/blob/main/media-types.md**[1]
- Docker Media Types: **https://docs.docker.com/registry/spec/manifest-v2-2/#media-types**[2]
使用Docker Manifest构建多架构镜像
编译不同架构的 Docker 镜像
bash
docker build -t app:latest-arm64 .
docker build -t app:latest-amd64 .合并不同架构的镜像到一个 manifest 中
bash
# 创建一个支持 x86 和 arm 的 manifest
docker manifest create --amend app:latest \
app:latest-amd64 \
app:latest-arm64
# Push manifest 到 Docker Registry
docker manifest push app:latest注意,这里是http 类型的 harbar 服务,如果不是请去除参数 --insecure:
bash# 创建一个支持 x86 和 arm 的 manifest docker manifest create --insecure --amend app:latest app:latest-amd64 app:latest-arm64 # Push manifest 到 Docker Registry docker manifest push --insecure app:latest
校验合并后的 manifest,确保创建成功
docker manifest inspect myapp:latest可以查看官方的文档 ,以深入了解有关自定义 Docker 镜像清单的内容。
个人实验版本
个人测试发现内网通过
moby/buildkit:buildx-stable-1创建构建器,并不能构建【如需尝试参考上面[配置Docker buildx环境](#配置Docker buildx环境)或者自行网上查找资料】
安装模拟器
bash
docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all当前支持的架构和已安装的模拟器
bashdocker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28
启用实验性功能
为了构建多平台镜像,需要确保 Docker 的实验性功能被启用,因为 buildx 依赖这些功能。通过修改 Docker 配置文件(通常位于 /etc/docker/daemon.json)来启用实验功能。
bash
vi /etc/docker/daemon.json
# 追加填入以下内容,确保json格式正确
{
"experimental": true
}执行以下命令
bash
systemctl daemon-reload
systemctl restart docker查看是否开启实验特性以及是否安装成功buildx
bash
docker version --format '{{.Server.Experimental}}'
# 如果结果为true则实验特性已经开启
docker buildx version构建镜像
bash
# docker pull 依赖镜像 --platform 依赖镜像架构
# docker buildx build --platform 目标架构 --tag ${IMAGE_TAG} -f Dockerfile文件,不指定默认Dockerfile --load .
docker pull 依赖镜像 --platform linux/amd64
docker buildx build --platform linux/amd64 --tag ${IMAGE_TAG} -f Dockerfile --load .
docker pull 依赖镜像 --platform linux/arm64
docker buildx build --platform linux/arm64 --tag ${IMAGE_TAG} -f Dockerfile --load .
...【--load】:通过这种方式会将镜像构建至本地
【--pull】:这种方式不适用,并不会自己拉取依赖镜像,需要手动
docker pull【--push】:这种方式不适用,并不能推送到目标仓库,需要手动
docker push