使用 docker manifest 构建多平台镜像
介绍
Docker manifest 是一个非常有用的工具,可以帮助你管理多架构镜像和多标签镜像。Docker Manifest 是 Docker 引入的一种机制,用于管理针对不同架构(如 amd64、arm64)或不同操作系统(如 Linux、Windows)构建的多个镜像。通过 Manifest,我们可以将这些镜像聚合在一起,形成一个统一的镜像引用,方便我们在不同环境中部署应用。
Docker Manifest 的优势
- 统一镜像引用: 使用一个统一的镜像名,就可以拉取适用于不同平台的镜像,简化了镜像管理。
- 自动化选择: Docker 自动根据运行环境选择合适的镜像,减少了手动操作。
- 提高部署效率: 减少了镜像构建和分发的次数,提高了部署效率。
- 简化镜像维护: 可以对多个镜像进行统一管理和更新。
Docker Manifest 的常见使用场景
- 多架构支持: 为不同的 CPU 架构(如 x86_64、arm64)构建镜像,并使用 Manifest 进行统一管理。
- 多操作系统支持: 为不同的操作系统(如 Linux、Windows)构建镜像,并使用 Manifest 进行统一管理。
- 多版本支持: 为同一个应用构建多个版本镜像,并使用 Manifest 进行管理。
使用 manifest 合并多平台镜像
查看是否开启 experimental 功能
--platform
参数需要 experimental
为 true
,通过下面的命令可以验证是否开启:
docker info | grep -i 'experimental'
开启experimental 功能配置:
参考:https://199604.com/2865
准备多平台镜像
首先,你需要为不同平台构建镜像。
可以使用 docker buildx
工具来构建这些镜像。例如:
docker buildx build --platform linux/amd64 -t myimage:amd64 .
docker buildx build --platform linux/arm64 -t myimage:arm64 .
也可以使用直接docker push
拉取不同平台镜像
# 拉取 ARM64 镜像
docker pull --platform="arm64" "docker.guoliangjun.com/redis:7"
docker tag "docker.guoliangjun.com/redis:7" "docker.guoliangjun.com/redis:7-arm64"
docker push "docker.guoliangjun.com/redis:7-arm64"
docker rmi "docker.guoliangjun.com/redis:7"
# 拉取 AMD64 镜像
docker pull --platform="amd64" "docker.guoliangjun.com/redis:7"
docker tag "docker.guoliangjun.com/redis:7" "docker.guoliangjun.com/redis:7-amd64"
docker push "docker.guoliangjun.com/redis:7-amd64"
docker rmi "docker.guoliangjun.com/redis:7"
创建 Manifes
使用 docker manifest create
命令创建一个新的 manifest,并将多个平台的镜像添加到该 manifest 中:
# 创建并推送 Docker Manifest
docker manifest create "docker.guoliangjun.com/redis:7" \
--amend "docker.guoliangjun.com/redis:7-arm64" \
--amend "docker.guoliangjun.com/redis:7-amd64"
推送 Manifes
将创建的 manifest 推送到镜像仓库
docker manifest push "docker.guoliangjun.com/redis:7"
# 验证 Manifest: 使用 docker manifest inspect 命令检查 manifest 的内容,确保所有架构的镜像都已正确添加:
docker manifest inspect docker.guoliangjun.com/redis:7
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1986,
"digest": "sha256:710b6a39f5ce580a3efda1d1307fee7c14dc99167f0217cd10c61c46f236a156",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1986,
"digest": "sha256:6993ed3665842588f0a46c770c5f9c473cabf3ecc27ef5af3db97f13ca3080d4",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
}
]
}
manifest 功能介绍
docker manifest
不止有 create
一个子命令,可以通过 --help/-h
参数查看使用帮助:
[root@localhost ~]# docker manifest --help
Usage: docker manifest COMMAND
The **docker manifest** command has subcommands for managing image manifests and
manifest lists. A manifest list allows you to use one name to refer to the same image
built for multiple architectures.
To see help for a subcommand, use:
docker manifest CMD --help
For full details on using docker manifest lists, see the registry v2 specification.
EXPERIMENTAL:
docker manifest is an experimental feature.
Experimental features provide early access to product functionality. These
features may change between releases without warning, or can be removed from a
future release. Learn more about experimental features in our documentation:
https://docs.docker.com/go/experimental/
Commands:
annotate Add additional information to a local image manifest
create Create a local manifest list for annotating and pushing to a registry
inspect Display an image manifest, or manifest list
push Push a manifest list to a repository
rm Delete one or more manifest lists from local storage
Run 'docker manifest COMMAND --help' for more information on a command.
docker manifest
共提供了annotate
、create
、inspect
、push
、rm
这 5 个子命。
create
[root@localhost ~]# docker manifest create --help
Flag shorthand -h has been deprecated, please use --help
Usage: docker manifest create MANIFEST_LIST MANIFEST [MANIFEST...]
Create a local manifest list for annotating and pushing to a registry
EXPERIMENTAL:
docker manifest create is an experimental feature.
Experimental features provide early access to product functionality. These
features may change between releases without warning, or can be removed from a
future release. Learn more about experimental features in our documentation:
https://docs.docker.com/go/experimental/
Options:
-a, --amend Amend an existing manifest list
--insecure Allow communication with an insecure registry
create
子命令支持两个可选参数-a/--amend
用来修订已存在的多架构镜像。
--insecure
参数则允许使用不安全的(非 https)镜像仓库。
push
使用 push
可以将多架构镜像推送到镜像仓库。
[root@localhost ~]# docker manifest push --help
Usage: docker manifest push [OPTIONS] MANIFEST_LIST
Push a manifest list to a repository
EXPERIMENTAL:
docker manifest push is an experimental feature.
Experimental features provide early access to product functionality. These
features may change between releases without warning, or can be removed from a
future release. Learn more about experimental features in our documentation:
https://docs.docker.com/go/experimental/
Options:
--insecure Allow push to an insecure registry
-p, --purge Remove the local manifest list after push
--insecure
参数允许使用不安全的(非 https)镜像仓库。
-p/--purge
选项的作用是推送本地镜像到远程仓库后,删除本地manifest list
。
inspect
inspect
用来查看 manifest
/manifest list
所包含的镜像信息。
[root@localhost ~]# docker manifest inspect --help
Usage: docker manifest inspect [OPTIONS] [MANIFEST_LIST] MANIFEST
Display an image manifest, or manifest list
EXPERIMENTAL:
docker manifest inspect is an experimental feature.
Experimental features provide early access to product functionality. These
features may change between releases without warning, or can be removed from a
future release. Learn more about experimental features in our documentation:
https://docs.docker.com/go/experimental/
Options:
--insecure Allow communication with an insecure registry
-v, --verbose Output additional info including layers and platform
--insecure
参数允许使用不安全的(非 https)镜像仓库。
-v/--verbose
参数可以输出更多信息,包括镜像的layers
和platform
信息。
annotate
annotate
子命令可以给一个本地镜像 manifest
添加附加的信息。
[root@localhost ~]# docker manifest annotate --help
Usage: docker manifest annotate [OPTIONS] MANIFEST_LIST MANIFEST
Add additional information to a local image manifest
EXPERIMENTAL:
docker manifest annotate is an experimental feature.
Experimental features provide early access to product functionality. These
features may change between releases without warning, or can be removed from a
future release. Learn more about experimental features in our documentation:
https://docs.docker.com/go/experimental/
Options:
--arch string Set architecture
--os string Set operating system
--os-features strings Set operating system feature
--os-version string Set operating system version
--variant string Set architecture variant
可选参数列表如下:
选项 | 描述 |
---|---|
--arch | 设置 CPU 架构信息。 |
--os | 设置操作系统信息。 |
--os-features | 设置操作系统功能信息。 |
--os-version | 设置操作系统版本信息。 |
--variant | 设置 CPU 架构的 variant 信息(翻译过来是“变种”的意思),如 ARM 架构的 v7、v8 等。 |
示例
# 创建 manifest
docker manifest create "docker.guoliangjun.com/redis:7" \
--amend "docker.guoliangjun.com/redis:7-arm64" \
--amend "docker.guoliangjun.com/redis:7-amd64"
# 注解 ARM64 镜像
docker manifest annotate docker.guoliangjun.com/redis:7 docker.guoliangjun.com/redis:7-arm64 --os linux --arch arm64
# 注解 AMD64 镜像
docker manifest annotate docker.guoliangjun.com/redis:7 docker.guoliangjun.com/redis:7-amd64 --os linux --arch amd64
# 推送 manifest
docker manifest push docker.guoliangjun.com/redis:7
rm
使用 rm
可以删除本地一个或多个多架构镜像(manifest lists
)。
[root@localhost ~]# docker manifest rm --help
Usage: docker manifest rm MANIFEST_LIST [MANIFEST_LIST...]
Delete one or more manifest lists from local storage
EXPERIMENTAL:
docker manifest rm is an experimental feature.
Experimental features provide early access to product functionality. These
features may change between releases without warning, or can be removed from a
future release. Learn more about experimental features in our documentation:
https://docs.docker.com/go/experimental/
# demo:
docker manifest rm docker.guoliangjun.com/redis:7
最后是一个合并的shell
manifest-images.sh
#!/bin/bash
# 读取 image.txt 文件中的每一行
for image in $(cat image.txt); do
# 拉取 ARM64 镜像
docker pull --platform="arm64" "docker.guoliangjun.com/$image"
docker tag "docker.guoliangjun.com/$image" "docker.guoliangjun.com/$image-arm64"
docker push "docker.guoliangjun.com/$image-arm64"
docker rmi "docker.guoliangjun.com/$image"
# 拉取 AMD64 镜像
docker pull --platform="amd64" "docker.guoliangjun.com/$image"
docker tag "docker.guoliangjun.com/$image" "docker.guoliangjun.com/$image-amd64"
docker push "docker.guoliangjun.com/$image-amd64"
docker rmi "docker.guoliangjun.com/$image"
# 创建并推送 Docker Manifest
docker manifest create "docker.guoliangjun.com/$image" \
--amend "docker.guoliangjun.com/$image-arm64" \
--amend "docker.guoliangjun.com/$image-amd64"
docker manifest push --purge "docker.guoliangjun.com/$image"
done