docker 多构架镜像

简介: 长久以来,主流计算机 CPU 都是 Intel x86 构架, AMD 将之扩展为 64 位 x86\_64 架构,又称为 amd64 。 “x86 CPU 有哪些?” “i5 i7 i386 i686 等” 。但主流并非唯一,业界一直存在多种 CPU 架构,如 MOS6502 MIPS PowerPC ARM 等。 Linux 很早就开始支持 ARM 的 64 位架构,社区称为 aarch64

长久以来,主流计算机 CPU 都是 Intel x86 构架, AMD 将之扩展为 64 位 x86\_64 架构,又称为 amd64 。 “x86 CPU 有哪些?” “i5 i7 i386 i686 等” 。但主流并非唯一,业界一直存在多种 CPU 架构,如 MOS6502 MIPS PowerPC ARM 等。 Linux 很早就开始支持 ARM 的 64 位架构,社区称为 aarch64 。近年来 ARM 市场份额逐渐扩大,主流为 64 位构架 (即 aarch64) ,一般又称为 arm64 。许多手机 CPU 都是 arm64 构架,MacBook 2021 年开始从 Intel CPU 切换到 arm64 CPU ,华为也在购买 ARM 授权后分别设计了用于手机和服务器的采用 arm64 构架的 CPU 。微软 Windows 11 也开始支持 arm64 构架。

x86\_64 是最流行的 CPU 构架,毫无疑问,这也是 docker 镜像率先重点支持的 CPU 构架。时光倒流到 2016 年,执行如下命令,默认拉取的即是 x86\_64 构架的镜像。

docker pull ubuntu:16.04

很快, docker 必须考虑支持其他多种 CPU 构架。如何支持呢?

镜像命名区分 CPU 构架

早期 docker 想到一个土办法:添加 CPU 架构名作为镜像命名空间前缀。如使用如下命令可分别拉取 amd64 和 arm64 构架的 ubuntu 镜像。

docker pull amd64/ubuntu:16.04
docker pull arm64v8/ubuntu:16.04

这个办法简单可用,但有一些问题。

CPU 构架 “规范” 名称

问题 1 : 如何确定 docker 约定的 CPU 构架 “规范” 名称是什么 ?

  • x86 64 位构架为什么不使用 “x86\_64” 而使用 “amd64” ?
  • ARM 64 位构架为什么即不使用 “aarch64” 也不使用 “arm64” 而是 “arm64v8” ?

使用 Tag 后缀区分构架

问题 2 : 许多镜像注册中心按命名空间进行权限管控,应用开发没有权限在其他命名空间下发布镜像,无法遵循使用 CPU 架构名作为命名空间前缀的约定。

变通办法是不使用命名空间前缀,改为使用镜像名或 Tag 前缀或后缀区分。个人偏向于添加 Tag 后缀的变通方案。如:

docker image pull hanyong/ubuntu:20.04-x86_64
docker image pull hanyong/ubuntu:20.04-aarch64

增加了使用镜像的复杂度

问题 3 : 不同的 CPU 构架下使用不同的镜像名,需要用户感知当前 CPU 构架对应的镜像名称 (或 Tag) , 增加了编写和维护 Dockerfile 的复杂性。

使用清单列表 (Manifest List) 支持多构架镜像

我是一名 Java 开发,我的工作电脑从 x86\_64 换成了 arm64 ,对我有什么影响?几乎毫无影响。操作系统和高级编程语言运行时封装了 CPU 构架等底层细节,无论什么 CPU 架构,编写的代码,使用的工具命令都是一样的,不需要感知 CPU 架构。

多个 CPU 构架下的镜像,提供了相同的逻辑功能,为什么要使用不同的镜像名呢?徒劳增加了开发者的认知负担。

因此,容器社区提出了使用统一的镜像名支持多种 CPU 构架的方案。 2017-09-12 后, docker 使用清单列表 (Manifest List) 功能实现了这一方案。

拉取多构架镜像

支持多架构镜像后,docker 自动根据当前 CPU 构架拉取对应的原生镜像。普通应用通常不需要感知 CPU 构架,基础镜像提供了相同的逻辑功能,此时只需要编写一份 Dockerfile ,在不同的 CPU 构架环境下,即可构建出当前 CPU 构架下的原生镜像。

# docker 自动根据当前 CPU 构架拉取对应的原生镜像
docker pull ubuntu:20.04

有时候我们可能需要处理跨 CPU 构架的镜像,如我是 arm64 的机器,但是想查看一个 x86\_64 构架的镜像,可以吗?可以,新版本 docker 的 pull 命令可使用 --platform 选项明确指定要拉取的具体镜像, platform 不仅可指定 CPU 构架信息,还可以指定操作系统信息。

  • 前面提到一种 CPU 构架可能有多个惯用名,如 x86\_64 和 amd64 ,命名空间前缀只能使用 docker 镜像注册中心约定的 “规范” 构架名,但 platform 参数使用任意一个惯用名均可,这也减轻了记忆 “规范” 构架名的负担。
  • ubuntu 等官方镜像仍然保留了使用 CPU 构架命名空间的单构架镜像,拉取单架构镜像时指定 --platform 选项无效。
  • 本机一个镜像名只能对应单个镜像,使用不同的 --platform 参数多次拉取一个镜像后,本机镜像名对应的镜像是最后一次拉取的镜像。

如下命令以两种方式显式拉取 x86\_64 构架的 ubuntu:20.04 镜像,可看到最终拉取到的是同一个镜像。

# 拉取 amd64 命名空间下的单架构镜像
docker image pull amd64/ubuntu:20.0
# 拉取多架构镜像在 x86_64 构架下的镜像
docker image pull --platform x86_64 ubuntu:20.04

创建多构架镜像

docker 使用清单列表 (Manifest List) 支持多构架镜像。

什么是清单? 将一个 docker 镜像推送到镜像注册中心后,镜像注册中心会记录镜像的存储信息,称为镜像清单 (Image Manifest) 。而清单列表则记录了多个镜像清单及其对应的平台 platform 信息。所谓多构架镜像,或多平台镜像,就是清单列表及其关联的多个单构架镜像。

创建多构架 (多平台) 镜像的操作步骤为:

  1. 创建多个单构架镜像。
  2. 将所有镜像推送到镜像注册中心,自动生成镜像清单。
  3. 汇总多个镜像清单得到清单列表,同样将清单列表推送 (存储) 到镜像注册中心上。新版本 docker 可使用 docker manifest 命令创建和推送清单列表。

Linux 支持交叉构建,即在一套环境下构建多种 CPU 构架下的镜像。为了简单起见,暂不讨论这种方案,暂采用在多个构架环境下创建各自的原生镜像的土办法。我使用的 docker 版本为 20.10.12 。这里以创建多架构镜像 hanyong/ubuntu:20.04 为例,介绍创建 docker 多构架镜像的实践操作步骤。

  1. 基于官方多架构镜像 ubuntu:20.04 编写 Dockerfile 。
  2. 在 x86\_64 机器上构建原生镜像,推送到镜像注册中心。 docker build --pull 表示每次构建前自动拉取最新的基础镜像,基础镜像是多架构镜像 (清单列表) 时,自动更新到当前架构的最新镜像。

    docker build --pull -t hanyong/ubuntu:20.04-x86_64 .
    docker push hanyong/ubuntu:20.04-x86_64
  3. 同样,在 arm64 机器上构建原生镜像,推送到镜像注册中心。

    docker build --pull -t hanyong/ubuntu:20.04-aarch64 .
    docker push hanyong/ubuntu:20.04-aarch64
  4. 使用推送到镜像注册中心的多个镜像创建清单列表。注意,前面为每个单架构镜像添加了不同的 Tag 后缀,以方便区分引用。将清单列表推送到镜像注册中心,删除本地副本 (清单列表只有存储在镜像注册中心上才有意义) 。

    docker manifest create hanyong/ubuntu:20.04 hanyong/ubuntu:20.04-x86_64 hanyong/ubuntu:20.04-aarch64
    docker manifest push hanyong/ubuntu:20.04
    docker manifest rm hanyong/ubuntu:20.04
相关文章
|
26天前
|
Docker 容器
将本地的应用程序打包成Docker镜像
将本地的应用程序打包成Docker镜像
|
10天前
|
NoSQL PHP MongoDB
docker push推送自己搭建的镜像
本文详细介绍了如何搭建和复盘两个Web安全挑战环境:人力资源管理系统和邮件管理系统。首先,通过Docker搭建MongoDB和PHP环境,模拟人力资源管理系统的漏洞,包括nosql注入和文件写入等。接着,复盘了如何利用这些漏洞获取flag。邮件管理系统部分,通过目录遍历、文件恢复和字符串比较等技术,逐步绕过验证并最终获取flag。文章提供了详细的步骤和代码示例,适合安全研究人员学习和实践。
36 3
docker push推送自己搭建的镜像
|
15天前
|
Docker 容器
|
27天前
|
数据库 Docker 容器
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。
Docker在现代软件开发中扮演着重要角色,通过Dockerfile自动化构建Docker镜像,实现高效、可重复的构建过程。Dockerfile定义了构建镜像所需的所有指令,包括基础镜像选择、软件安装、文件复制等,极大提高了开发和部署的灵活性与一致性。掌握Dockerfile的编写,对于提升软件开发效率和环境管理具有重要意义。
51 9
|
1月前
|
缓存 Linux 网络安全
docker的镜像无法下载如何解决?
【10月更文挑战第31天】docker的镜像无法下载如何解决?
2080 30
|
27天前
|
存储 缓存 运维
Docker镜像采用分层存储,每层代表镜像的一部分,如基础组件或应用依赖,多层叠加构成完整镜像
Docker镜像采用分层存储,每层代表镜像的一部分,如基础组件或应用依赖,多层叠加构成完整镜像。此机制减少存储占用,提高构建和传输效率。Docker还通过缓存机制提升构建和运行效率,减少重复工作。文章深入解析了Docker镜像分层存储与缓存机制,包括具体实现、管理优化及实际应用案例,帮助读者全面理解其优势与挑战。
44 4
|
2月前
|
缓存 监控 持续交付
|
1月前
|
存储 关系型数据库 Linux
【赵渝强老师】什么是Docker的镜像
Docker镜像是一个只读模板,包含应用程序及其运行所需的依赖环境。镜像采用分层文件系统,每次修改都会以读写层形式添加到原只读模板上。内核bootfs用于加载Linux内核,根镜像相当于操作系统,上方为应用层。镜像在物理存储上是一系列文件的集合,默认存储路径为“/var/lib/docker”。
|
1月前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
163 2
|
1月前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
207 1

热门文章

最新文章