阅读更多

0顶
0踩

行业应用

原创新闻 构建多CPU架构支持的Docker镜像

2018-01-24 10:40 by 副主编 jihong10102006 评论(0) 有10954人浏览
引用
作者简介:胡晓亮目前就职于IBM Platform Computing 系统科技部云计算部门,担任云计算开发部工程师。自2013年8月开始参与OpenStack,然后又转战Spark,目前工作在K8S相关领域。
责编:钱曙光(qianshg@csdn.net)

Docker简介

由于基于Hypervisor虚拟化技术仍然存在一些性能和资源使用效率方面的问题,近3年来容器技术席卷了整个互联网应用乃至IT界的技术革新,成为一种被大家广泛认可的服务器资源共享技术。它从根本上变革了应用程序的开发和发布方式,经过爆炸式的成长,容积技术的翘楚Docker实际上已经成为了容器格式和运行时的标准,大量流行的开源应用程序都宣布支持容器化,并且一些企业级的应用程序也开始往容器上迁移, Docker容器世界欣欣向荣。

Multi architecture Docker镜像

Multi architecture Docker镜像的支持让Docker向自己宣称的口号 “Build, Ship, and Run Any App, Anywhere” 更近了一大步。 那什么是Multi architecture Docker镜像呢?我们可以通过一个例子来说明。我们知道JAVA语言编写的应用程序是 “Write once, run anywhere”,它体现了JAVA跨平台的特性,但是JAVA程序的运行环境JVM(JAVA 虚拟机)却不是跨平台的,它是JAVA应用程序和OS平台之间的一个桥梁,不同的类型的OS和CPU架构机器需要安装相应的JVM才能运行JAVA程序。而 Docker image也是一样的,它也是依赖运行平台的,我们不能把一个httpd的ppc64le/linux架构的Docker镜像运行在amd64/linux 架构的环境中,我们也不能把一个Windows镜像运行在Linux平台上,否则你会遇到 “exec format error”。早期Docker镜像存储的设计没有充分考虑到镜像Multi architecture的支持,而是简单的使用镜像存储库的前缀来区分相同应用的不同平台,并建议开发者将不同平台的镜像应该push到相对应的Docker hub的镜像仓库中,而这种糟糕的设计依然保留在最新的Docker设计文档中如下:
例如运行busybox在多个平台上,按照Docker社区的方法如下:
x86-64:     docker run -it --rm busybox or docker run -it --rm amd64/busybox
ppc64le:   docker run -it --rm ppc64le/busybox 
s390x:      docker run -it --rm s390x/busybox 

基于Docker社区的做法,对于我们自己的应用程序Docker镜像多平台支持,我们还可以采取类似方法:

1. 基于tag
x86-64:    docker run -it --rm myapp:x86-64
ppc64le:  docker run -it --rm myapp:ppc64le
s390x:      docker run -it --rm myapp:s390x

2. 基于image 名称的后缀
x86-64:    docker run -it --rm myapp_x86-64
ppc64le:  docker run -it --rm myapp_ppc64le
s390x:      docker run -it --rm myapp_s390x

不管是基于镜像存储库的前缀,或者是基于tag或image名称后缀来区分不同的运行平台来pull相应的Docker镜像都不是好的设计,而好的设计是应该用户只要执行docker pull myapp就行了而不用关心容器的运行平台,Docker engine根据运行环境来pull相关的镜像,真正的做到 “Run Any App, Anywhere”。Docker社区已经注意到了这个问题,通过重新定义 v2.2 Image specification format(PR #1068)并在 Implement schema2 manifest formats(PR #1281)实现了Multi architecture Docker镜像功能。从Docker registry v2.3和Docker 1.10 开始,Docker hub就可以pull multi architecture Docker镜像了.

例如有2个Linux host,一个host(kvm-014009)arch是x86_64,另一个host(power807l )arch是ppc64le,我们分别在两个host 上运行 busybox 容器并且打印容器中基础镜像的arch, 看看是不是pull相同的镜像但是可以打印出与平台相关的输出。
x86_64 host :

[root@kvm-014009 ~]# docker run -it --rm busybox arch

Unable to find image 'busybox:latest' locally

latest: Pulling from library/busybox

67a0688b88df: Pull complete 

Digest: sha256:ac2fc418f3348815e68e266a5aa1b60bc522581c96964912560a0baacc4f5c06

Status: Downloaded newer image for busybox:latest

x86_64

ppc64le host:

[root@power807l ~]# docker run -it --rm busybox arch

Unable to find image 'busybox:latest' locally

latest: Pulling from library/busybox

219992aaea40: Pull complete 

Digest: sha256:ac2fc418f3348815e68e266a5aa1b60bc522581c96964912560a0baacc4f5c06

Status: Downloaded newer image for busybox:latest

ppc64le

我们run了相同的命令 “docker run -it –rm busybox arch” 在不同CPU architecture的host都得到了正确的运行结果,这是用户体验的一个极大的提升,用户根本不用关心 image的CPU arch 和OS的类型了。除了busybox镜像,httpd,nginx, tomcat和etcd等主流开源应用都有了Multi architecture Docker镜像支持,大家快快试试吧。

原理分析

如上文我们提到的自从Docker registry v2.3和Docker 1.10开始,Docker通过支持新的image Media 类型 manifest list 实现了Multi architecture Docker镜像功能:

1. 一个image manifest list 包含指向已经存在镜像的manifest对象列表

2. 一个image manifest list包含已经存在镜像的manifest对象的平台特性(CPU arch和OS类型)特征

根据manifest list对象定义,我们可以通过下面的流程了解Docker是如何支持Multi architecture Docker镜像的:

动手实验
制作一个multi architecture Docker镜像最重要的是定义image的manifest list,虽然image manifest list的标准已经确定也实现了,可是客户端如何push这个image的manifest list到Docker registry依然在Docker社区争论不休,有兴趣的同学可以看一下ticket Add manifest command了解一下细节。虽然还没有Docker official的客户端工具支持,但是广大的开源爱好者们还是自己根据 v2.2 Image specification format中的定义实现一些小工具可以帮助我们制作multi architecture Docker镜像。首先给大家介绍两个小工具,他们都可以push Docker image的manifest list到Docker registry中。

1. Enhanced Docker CLI

这是加强版的Docker CLI,他的code base 是基于社区的Docker CLI,并且marge了 Docker官方的Add manifest command这个pull request,它很好的集成了现有的Docker CLI, 并且增加了docker manifest的sub command 支持。

2. Manifest-tool

这是一个独立的小工具,它也实现了v2.2 Image specification format,并且支持查看,创建和push manifests list 对象到Docker registry,并且更加方便易用,因为它可以使用yaml文件定义image manifest list对象。

实验机器
Host CPU arch OS Docker version
kvm-014009 x86_64 Linux rhel 7.3 Server: 17.03.2-ce
power807l ppc64le Linux rhel 7.4 Server: 17.05.0-ce

先决条件

  • 从source code编译出两个小工具的可执行文件 docker 和 manifest-tool,我们可以参考两个小工具github中提供的步骤,或者直接使用我编译好的x86_64平台的可执行文件
  • 有一个可用的Docker hub 账号用来push镜像,假设这个账户是huxl,并且已经docker login成功
实验目的

假设有一个叫myapp是跨平台的应用,支持x86_64和ppc64le CPU arch 和Linux, 为了简单,在假设myapp就是一个文本文件,里面只有一句话:I am x86_64 application (for x86_64) 或者 I am ppc64le application (for ppc64le), Dockerfile也很简单如下,用户可以使用一致的命令run这个myapp应用在不同的平台上。
FROM alpine

WORKDIR /opt

COPY myapp .

实验步骤:

1、使用Enhanced Docker CLI构建multi architecture Docker镜像

a. 构建myapp的x86_64镜像,并且push到Docker hub上
            [root@kvm-014314 muti-arch]# docker build -t huxl/myapp-x86_64:v1 .

            Sending build context to Docker daemon 3.072 kB

            Step 1/3 : FROM alpine

            latest: Pulling from library/alpine

            ff3a5c916c92: Pull complete 

            Digest: sha256:7df6db5aa61ae9480f52f0b3a06a140ab98d427f86d8d5de0bedab9b8df6b1c0

            Status: Downloaded newer image for alpine:latest

             ---> 3fd9065eaf02

            Step 2/3 : WORKDIR /opt

             ---> 204fec0aa91b

            Removing intermediate container 49747c6124e8

            Step 3/3 : COPY myapp .

             ---> d89721162bd0

            Removing intermediate container b63c71aebd49

            Successfully built d89721162bd0

            [root@kvm-014314 muti-arch]# docker push huxl/myapp-x86_64:v1 

            The push refers to a repository [docker.io/huxl/myapp-x86_64]

            723ba289c543: Pushed 

            7b2f1ea92884: Pushed 

            cd7100a72410: Mounted from library/alpine 

            v1: digest: sha256:ffac5d9918844da37c707e5b8690ce6f75563611bb6326daa5620fcb853bb590 size: 941

b. 构建myapp的ppc64le镜像,并且push到Docker hub上
           
[root@power807l muti-arch]# docker build -t huxl/myapp-ppc64le:v1 .

            Sending build context to Docker daemon  3.072kB

            Step 1/3 : FROM alpine

            latest: Pulling from library/alpine

            0da653ea85b5: Pull complete 

            9fd90b777cc3: Pull complete 

            Digest: sha256:7df6db5aa61ae9480f52f0b3a06a140ab98d427f86d8d5de0bedab9b8df6b1c0

            Status: Downloaded newer image for alpine:latest

             ---> 5675e84fb0f7

            Step 2/3 : WORKDIR /opt

             ---> fe7e5331969e

            Removing intermediate container 91c27a07b969

            Step 3/3 : COPY myapp .

             ---> e2e2fd0b2abb

            Removing intermediate container c24a46b56e1e

            Successfully built e2e2fd0b2abb

            Successfully tagged huxl/myapp-ppc64le:v1

            [root@power807l muti-arch]# docker push huxl/myapp-ppc64le:v1 

            The push refers to a repository [docker.io/huxl/myapp-ppc64le]

            4abe83ad0ae2: Pushed 

            30b0e74edb8c: Pushed 

            d8f649dc98c5: Pushed 

            22963f19a0a3: Mounted from library/alpine 

            v1: digest: sha256:102f93c9ae146cbf2d5247db82e4429f5964978cfda1df72a9c7e444a4840437 size: 1148

            [root@power807l muti-arch]# 

c. 创建指向myappp的x86_64和ppc64le的镜像的manifests list对象并将它push到docker hub
           
[root@kvm-014314 build]# pwd

            /root/cli/build

            [root@kvm-014314 build]# ./docker manifest create huxl/myapp:v1 huxl/myapp-x86_64:v1 huxl/myapp-ppc64le:v1

            Created manifest list docker.io/huxl/myapp:v1

            [root@kvm-014314 build]# ./docker manifest annotate huxl/myapp:v1 huxl/myapp-x86_64:v1 --os linux --arch amd64

            [root@kvm-014314 build]# ./docker manifest annotate huxl/myapp:v1 huxl/myapp-ppc64le:v1 --os linux --arch ppc64le

            [root@kvm-014314 build]# ./docker manifest push huxl/myapp:v1

            Pushed ref docker.io/huxl/myapp@sha256:102f93c9ae146cbf2d5247db82e4429f5964978cfda1df72a9c7e444a4840437 with digest: sha256:102f93c9ae146cbf2d5247db82e4429f5964978cfda1df72a9c7e444a4840437

            Pushed ref docker.io/huxl/myapp@sha256:ffac5d9918844da37c707e5b8690ce6f75563611bb6326daa5620fcb853bb590 with digest: sha256:ffac5d9918844da37c707e5b8690ce6f75563611bb6326daa5620fcb853bb590

            sha256:b1b4c2219f5f514fe5a752d158c76b3aa010fab2b1e1dbfa808755ff0848abfa

            [root@kvm-014314 build]#

d. 验证run myapp 镜像在两个host上,我们得到了不同的结果
          
 [root@kvm-014314 build]# docker run -it  --rm huxl/myapp:v1 cat /opt/myapp

            Unable to find image 'huxl/myapp:v1' locally

            v1: Pulling from huxl/myapp

            Digest: sha256:b1b4c2219f5f514fe5a752d158c76b3aa010fab2b1e1dbfa808755ff0848abfa

            Status: Downloaded newer image for huxl/myapp:v1

            I am x86_64 application

            [root@kvm-014314 build]# 


            [root@power807l muti-arch]# docker run -it  --rm huxl/myapp:v1 cat /opt/myapp

            Unable to find image 'huxl/myapp:v1' locally

            v1: Pulling from huxl/myapp

            Digest: sha256:b1b4c2219f5f514fe5a752d158c76b3aa010fab2b1e1dbfa808755ff0848abfa

            Status: Downloaded newer image for huxl/myapp:v1

            I am pcc64le application

            [root@power807l muti-arch]#

e. 从Docker hub上删除huxl/myapp:v1,后面我们使用Manifest-tool重新创建它
f. 删除本地huxl/myapp:v1镜像,为了不影响后续的实验
          
 [root@kvm-014314 manifest-tool]# docker rmi -f huxl/myapp:v1

            Untagged: huxl/myapp:v1

            Untagged: huxl/myapp@sha256:b1b4c2219f5f514fe5a752d158c76b3aa010fab2b1e1dbfa808755ff0848abfa

            [root@kvm-014314 manifest-tool]# 


            [root@power807l ~]# docker rmi -f huxl/myapp:v1

            Untagged: huxl/myapp:v1

            Untagged: huxl/myapp@sha256:b1b4c2219f5f514fe5a752d158c76b3aa010fab2b1e1dbfa808755ff0848abfa

            [root@power807l ~]# 

2、使用Manifest-tool 构建multi architecture docke的镜像

a. 创建一个yaml文件用来表述支持multi architecture的镜像myapp:v1
         
  [root@kvm-014314 manifest-tool]# pwd

            /root/manifest-tool

            [root@kvm-014314 manifest-tool]# cat myapp.yaml 

            image: huxl/myapp:v1

            manifests:

              -

                image: huxl/myapp-ppc64le:v1

                platform:

                  architecture: ppc64le

                  os: linux

              -

                image: huxl/myapp-x86_64:v1

                platform:

                  architecture: amd64

                  os: linux

            [root@kvm-014314 manifest-tool]# 

b. push myapp.yaml到docker hub
           
[root@kvm-014314 manifest-tool]# pwd

            /root/manifest-tool

            [root@kvm-014314 manifest-tool]# ./manifest-tool push from-spec myapp.yaml  

            Digest: sha256:dcf22c78689691df6d68117d55c4a4ce6b745caa38b1f31e882fc358a742c3c5 744

            [root@kvm-014314 manifest-tool]#

c. 验证run myapp 镜像在两个host上,我们都得到了正确的结果
          
 [root@kvm-014314 manifest-tool]# docker run -it  --rm huxl/myapp:v1 cat /opt/myapp

            Unable to find image 'huxl/myapp:v1' locally

            v1: Pulling from huxl/myapp

            Digest: sha256:dcf22c78689691df6d68117d55c4a4ce6b745caa38b1f31e882fc358a742c3c5

            Status: Downloaded newer image for huxl/myapp:v1

            I am x86_64 application

            [root@kvm-014314 manifest-tool]# 


            [root@power807l muti-arch]# docker run -it  --rm huxl/myapp:v1 cat /opt/myapp

            Unable to find image 'huxl/myapp:v1' locally

            v1: Pulling from huxl/myapp

            Digest: sha256:dcf22c78689691df6d68117d55c4a4ce6b745caa38b1f31e882fc358a742c3c5

            Status: Downloaded newer image for huxl/myapp:v1

            I am pcc64le application

            [root@power807l muti-arch]#

Note:我们可以使用命令docker manifest inspect huxl/myapp:v1 或者 manifest-tool inspect huxl/mycool-app:v1看到这个multi architecture Docker镜像的manifest list,这里就不在赘述了。

总结
  • Push multi architecture Docker镜像到Docker registry并不会push image的layers,它只会push一个引用,这个引用指向了已经存在的多个Docker镜像;
  • 只有multi architecture Docker镜像的创建者才需要知道这个引用背后指向具体的Docker镜像,而对最终的用户是透明的,最终用户只需要知道镜像的名字和tag就足够了;
  • 有了multi architecture Docker镜像支持,我们再也不用在脚本里面判断OS的类型和CPU的arch而去pull相应的镜像,提高CICD代码的简洁和优雅;
  • Image manifest list是极好的兼容性设计,它不但支持multi architecture Docker镜像,而且不会影响已经在的simple architecture Docker镜像的使用方式, 用户不用做二选一的艰难的决定。
  • 大小: 195.7 KB
  • 大小: 7.8 KB
  • 大小: 22.1 KB
  • 大小: 22.1 KB
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • ASP.NET WEB介绍

    我的ASP.NET 第一讲 ASP.NET 入门 ASP.NET 是动态 网络 语言。那么运行 在服务器中,在这里我们始终离不开浏览器的角色,因此在学习网页开发先了解浏览器: 浏览器的介绍 一.五大浏览器:* 1.浏览器有哪些? **Internet Explorer (IE), Trident内核: FireFox(火狐), Gecko内核: C...

  • 利用ASP.NET快速开发一款Web应用

    需要用到的技术 .NET CORE 2.1:一个跨平台的高性能开源框架,用于生成启用云且连接 Internet 的新式应用 ASP.NET MVC:一种使用“模型-视图-控制器”设计模式构建 Web 应用和 API 的框架 ASP Razor Page:一种混合HTML和.NET语言而开发的服务端页面 SQL Server:一种关系型数据库 EF Code First:代码优先实体框架,一种迁移脚手架工具,以代码模型类为驱动的数据库表结构自动构建与更新同步工具。 BootStrap/EChart

  • ASP.NET 创建、发布、使用Web服务的详细方法

    一、创建Web服务 1.首先,打开VS(本例以VS2017为例) 创建一个ASP.NET Web 应用程序,位置和名称自定义,本例我把这个项目创建在桌面,名字叫helloWho。然后点击【确定】,在弹出的下一个对话框中,选择“空”,其他保存默认不变,最后点击【确定】,完成项目的创建。 2.右击项目名→【添加】→【新建项】, 在弹出的“添加新项”对话框中,找的“Web服务”,给Web服务起名,本例起名为Hello。最后点击【添加】,完成Web服务的添...

  • ASP.NET Web程序设计笔记

    超文本传输协议最简单的ASP.NET模型内置了用于数据库、视频、社交媒体等的模板和帮助器传统的ASP.NET事件驱动开发模型添加了服务器控件、服务器事件以及服务器代码的网页3.1.3.MVCMVC编程模型是与传统的ASP.NET(Web Forms)相比更轻量级的替代方案轻量级的可测试性的框架,同时整合了所有已有的ASP.NET特性,比如模板页。安全性和认证CustomValidator控件用于执行自定义验证CustomValidator控件常用属性和事件属性说明。

  • C#使用Asp.Net创建Web Service接口并调用

    开发工具: Visual Studio 2022 Current (免费社区版)框架版本: .net framework4.7.2,更高的.net 5 、net6貌似没有默认提供带web service的asp.net 应用模板了。确保VS的工作负荷有勾选下方箭头所指的模块确认环境没有问题之后就可以开始创建项目了。

  • 【C# 10 和 .NET 6】构建和使用 Web 服务(第16章)

    Building and Consuming Web Services构建和使用 Web 服务本章介绍如何使用 ASP.NET Core Web API 构建 Web 服务(也称为 HTTP 或 REST 服务),以及如何使用 HTTP 客户端使用 Web 服务,这些客户端可以是任何其他类型的 .NET 应用程序,包括网站或移动设备或 桌面应用程序。本章需要您在第 10 章“使用 Entity ...

  • web服务器工作原理是什么?

    尽管它最初是为NCSAhttpd服务器而设计方案的,在改网络服务器新项目终止后,互换了该网络服务器的补丁下载而成,可是,它的主要风采取决于它对外开放的源码,另外有着一支强势的技术性精英团队,还能混合开发适用,能够运作在现阶段整体的流行的网站服务器上,可移植性很强。③应答过程就是运用HTTP协议把在请求过程中所提出来的请求传输到Web的服务器,进而实施任务处理,然后运用HTTP协议把任务处理的结果传输到Web的浏览器,同时在Web的浏览器上面展示上述所请求之界面。2、web服务器的工作原理是什么?

  • asp.net访问WebService的各种方式

    WebService的访问形式主要有:SOAP调用、XMLHTTP POST、GET调用、MicroSoft.XMLDOMC调用、webbehavior.htc调用我们知道的在C#后台本地调用Webservice最简单、快捷的调用WebService的方法即通过鼠标手动添加web服务引用的方式。实际操作中我们会使用到另外一种方式,即通过HttpWebRequest构造请求。这种方式下以Post和G...

  • ASP.NET_Web服务器和网站配置

    内置的Web开发服务器 当项目在本地计算机调试时 调试运行后自行启动 iis服务器

  • 【ASP.NET MVC系列】浅谈ASP.NET 程序发布过程

    ASP.NET MVC系列文章 【01】浅谈Google Chrome浏览器(理论篇) 【02】浅谈Google Chrome浏览器(操作篇)(上) 【03】浅谈Google Chrome浏览器(操作篇)(下) 【04】浅谈ASP.NET框架    【05】浅谈ASP.NET MVC运行过程     【06】浅谈ASP.NET MVC 控制器    【07】浅谈ASP.NET M...

  • 性能比较:.NET Remoting 与 ASP.NET Web 服务

    要:本文对 Microsoft ASP.NET Web 服务与 Microsoft .NET Remoting 的相对性能进行比较。Microsoft ASP.NET Web 服务的互操作性最好,并完全支持 HTTP 上的 WSDL 和 SOAP;而 Microsoft .NET Remoting 可实现公共语言运行库类型系统的高保真,并支持其他数据格式和通信通道。 从 MSDN Code Ce...

  • .net实现webservice简单实例

    原理:WebService是一个SOA(面向服务的编程)的架构,它是不依赖于语言,不依赖于平台,可以实现不同的语言间的相互调用,通过Internet进行基于Http协议的网络应用间的交互。 作用:主要用于数据交换、提供服务接口 优点:可跨平台、部署简单调用方便、无需额外客户端支持 一、创建一个WebService服务 1.创建一个普通的Asp.Net Web应用程序,名称为WebSer

  • net开源开发web框架_我的6大Web开发开源框架

    net开源开发web框架 有许多后端框架是开源的,并且易于使用,但是并非所有框架都提供了出色的功能。 后端框架是网站开发的重要组成部分,因为它们就像网站的基本要素。 基本上,他们处理网站幕后的一切。 后端框架具有广泛的库,API,Web服务器等。 他们负责数据库,确保数据库与前端进行正确的通信并生成后端功能。 如所承诺的,接下来是我的前6个后端框架的摘要。 1. Ruby on Ra...

  • ASP.NET WEB网站简单入门(简单Demo ->发布)

    简单分几个阶段 一、简单代码实现 1.新建工程 2.打开设计器(查看设计器),托出一个label ,写上Hello 3.点击调试,即可看到网页效果 4.重新生成后,发布到指定路径下 5.弹出网站发布设置面板,点击<新建..>,创建新的发布配置文件: 6.输入你自己定义的配置文件名: 7.点击下一步:在发布方法中选“文件系统”,这样我们可以发布到自...

  • ASP.NET 服务程序的发布

    ASP.NET 服务程序的发布 编译器:VS2010旗舰版 OS:Windows Xp SP3 第一步:打开VS2010 第二步:文件新建项目 第三步:如下图 第四步:右键解决方案添加新建网站 第五步:如下图 注:如果:你在的编译器中看不到 .Net Framewrok 3.5 请下载.Net Framewrok 3.5 SP1

  • .net 调用webservice 总结

    最近做一个项目,由于是在别人框架里开发app,导致了很多限制,其中一个就是不能直接引用webservice 。 我们都知道,调用webserivice 最简单的方法就是在 "引用"  那里点击右键,然后选择"引用web服务",再输入服务地址。 确定后,会生成一个app.config 里面就会自动生成了一些配置信息。 现在正在做的这个项目就不能这么干。后来经过一番搜索,就找出另外几种动态调用w...

  • asp.net(4.7) 的微服务之路系列一

    虽然大家都希望所有的应用都尽快迁移到dotnet core 平台之上,然而由于需要重构代码,改造不被dotnet core支持的功能,因此,应用的改造也非一日之功,特别是线上的平台更是如此,如何能够尽快微服务化,以便享受到容器带来的更多优势呢?这个系列让你步入docker的世界……   搭建环境 准备:环境操作系统必须选用 Windows Server 2016 (或更高版本),这里...

Global site tag (gtag.js) - Google Analytics