docker 多个环境装在一个镜像内(docker如何编辑已经构建好的镜像)

技术Docker镜像怎么做到一次构建,到处运行这篇文章主要介绍“Docker镜像怎么做到一次构建,到处运行”,在日常操作中,相信很多人在Docker镜像怎么做到一次构建,到处运行问题上存在疑惑,小编查阅了各式资料,整理出

本文主要介绍“如何一次建立Docker映像,随处运行”。在日常操作中,相信很多人对于如何一次建立Docker形象,到处跑都有疑问。边肖查阅了各种资料,整理出简单易用的操作方法,希望能帮你解答“如何一次打造Docker形象,到处跑”的疑惑!接下来,请和边肖一起学习!

方法 1:直接在目标硬件上构建

如果我们可以访问目标架构硬件,并且操作系统拥有我们需要的所有构建数据,那么我们可以直接在硬件上编译应用程序。

例如,为了在我们的特定场景中构建多架构Docker映像,我们可以在树莓派上安装Docker运行时环境,然后通过应用程序的Dockerfile直接在其上构建映像,就像在开发机器上一样。这种方法是可行的,因为Raspbian的官方操作系统Raspbian支持Docker的本地安装。

但是如果我们不能方便地访问目标硬件呢?我们可以直接在开发机器上构建非原生架构应用程序吗?

方法 2:模拟目标硬件

还记得16台任天堂游戏机的快乐时光吗?那时候我还只是个孩子,但长大后发现自己非常怀念《超级玛丽》、《时空之轮》等经典游戏。但是我没有机会拥有一台超级任天堂游戏主机,但是得益于ZSNES这样的模拟器,我可以回到过去,在32位个人电脑上体验这些经典游戏的乐趣。

通过模拟器,我们不仅可以玩电子游戏,还可以构建非本机二进制文件。当然,我们用的不是ZSNES,而是一个更强大更灵活的模拟器:QEMU。QEMU是一个免费的开源模拟器,支持很多常见的架构,包括ARM、Power-PC和RISC-V,通过运行一个全功能的模拟器,我们可以启动一个可以运行Linux操作系统的通用ARM虚拟机,然后在虚拟机中设置开发环境并编译应用程序。

但是,仔细想想,一个功能齐全的虚拟机会浪费一些资源。在这种模式下,QEMU将模拟整个系统,包括定时器、存储控制器、SPI和I2C总线控制器等硬件。然而,在大多数情况下,我们编译应用程序时没有注意上面提到的硬件特性。还能更好吗?

方法 3:通过 binfmt_misc 模拟目标架构的用户空间

在Linux系统上,QEMU还有另一种操作模式,可以通过用户模式模拟器运行非原生架构的二进制程序。在这种模式下,QEMU将跳过方法2中描述的整个目标系统硬件的模拟。而是会通过binfmt_misc在Linux内核中注册一个二进制格式的处理程序,在执行之前对不熟悉的二进制代码进行拦截和转换,同时根据需要将系统调用从目标系统转换到当前系统。最后,对于用户来说,他们会发现可以在本地运行这些异构的二进制程序。

借助用户模式模拟器和QEMU,我们可以通过轻量级虚拟化(chroot或container)安装其他Linux发行版,并像本地一样编译我们需要的异构二进制程序。

我们将在下面看到,这将是构建多架构Docker映像的替代方式。

方法 4:使用交叉编译器

最后,我们在嵌入式系统社区中有另一个标准实践:交叉编译。

交叉编译器是一种特殊的编译器,它运行在主机架构上,但可以为不同的目标架构生成二进制程序。比如我们可以有一个基于amd64架构的C交叉编译器,目标架构是aarch74(64位ARM)的嵌入式设备(比如智能手机什么的)。基于这种方法的一个实际例子是,世界上有数十亿的安卓设备使用这种方法来构建软件。

从性能的角度来看,这种方法与直接在目标硬件上构建具有相同的效率(方法1),因为它不在模拟器上运行。但是交叉编译的变量取决于使用的编程语言,如果是Go语言就非常方便了。

搞糊涂了吗?对于 Docker 镜像来说会更复杂hellip;hellip;

请注意,上面提到的所有编译方法只生成一个应用程序二进制文件。对于现代容器,当我们引入Docker映像时,不仅仅是构建单个二进制文件,而是构建一个完整的异构容器映像!这比以前更麻烦了。

如果这一切听起来很痛苦,不要难过,因为为非原生平台构建二进制文件本来就很痛苦。在此基础上增加Docker带来的复杂性似乎要留给专家来处理。

得益于Docker运行时环境最新版本带来的实验性扩展,现在构建多架构映像比以前方便多了。

00-1010为了更方便地构建多架构Docker映像,我们可以使用最近发布的Docker扩展:buildx。Buildx是下一代标准docker build命令的前端,这是构建docker映像的熟悉命令。借助BuildKit的所有功能,buildx扩展了表中docker build命令的功能,成为Docker build系统的新后端。

>让我们花几分钟看下如何使用 buildx 来构建多架构镜像。

步骤 1:开启 buildx

要使用 buildx,首先要确认我们的 Docker 运行时环境已经是最新版本 19.03。新版本中,buildx 事实上已经默认和 Docker  捆绑在一起,但是需要通过设置环境变量 DOCKER_CLI_EXPERIMENTAL 来开启。让我们在当前命令行会话中开启:

$ export DOCKER_CLI_EXPERIMENTAL=enabled

通过检查版本来验证目前我们已经可以使用 buildx:

$ docker buildx version github.com/docker/buildx v0.3.1-tp-docker 6db68d029599c6710a32aa7adcba8e5a344795a7

可选步骤:从源码构建

如果要使用最新版本的 buildx,或者在当前环境下设置 DOCKER_CLI_EXPERIMENTAL 环境变量不生效(例如我发现在 Arch  Linux 系统中设置无效),我们可以从源码构建 buildx:

$ export DOCKER_BUILDKIT=1 $ docker build --platform=local -o . git://github.com/docker/buildx $ mkdir -p ~/.docker/cli-plugins && mv buildx ~/.docker/cli-plugins/docker-buildx

步骤 2:开启 binfmt_misc 来运行非本地架构 Docker 镜像

如果读者使用的是 Mac 或者 Windows 版本 Docker 桌面版,可以跳过这个步骤,因为 binfmt_misc 默认开启。

如果使用是 Linux 系统,需要设置 binfmt_misc。在大部分发行版中,这个操作非常简单,但是现在可以通过运行一个特权 Docker  容器来更方便的设置:

$ docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d

通过检查 QEMU 处理程序来验证 binfmt_misc 设置是否正确:

$ ls -al /proc/sys/fs/binfmt_misc/ total 0 drwxr-xr-x 2 root root 0 Nov 12 09:19 . dr-xr-xr-x 1 root root 0 Nov 12 09:16 .. -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-aarch74 -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-arm -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-ppc64le -rw-r--r-- 1 root root 0 Nov 12 09:25 qemu-s390x --w------- 1 root root 0 Nov 12 09:19 register -rw-r--r-- 1 root root 0 Nov 12 09:19 status

然后,验证下指定架构处理程序已经启用,例如:

$ cat /proc/sys/fs/binfmt_misc/qemu-aarch74 enabled interpreter /usr/bin/qemu-aarch74 flags: OCF offset 0 magic 7f454c460201010000000000000000000200b7 mask ffffffffffffff00fffffffffffffffffeffff

步骤 3:将默认 Docker 镜像构建器切换成多架构构建器

默认情况下,Docker 会使用旧的构建器,不支持多架构构建。

为了创建一个新的支持多架构的构建器,运行:

$ docker buildx create --use --name mybuilder

验证新的构建器已经生效:

$ docker buildx ls NAME/NODE    DRIVER/ENDPOINT             STATUS   PLATFORMS mybuilder *  docker-container   mybuilder0 unix:///var/run/docker.sock inactive default      docker   default    default                     running  linux/amd64, linux/arm64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

搞定。现在 Docker 会使用新的构建器,支持构建多架构镜像。

步骤 4:构建多架构镜像

好了,现在我们终于可以开始构建一个多架构镜像了。为了演示这个功能,我们需要一个示例应用。

让我们创建一个简单的 Go 应用程序,输出当前运行环境的架构信息:

$ cat hello.go package main  import (         "fmt"         "runtime" )  func main() {         fmt.Printf("Hello, %s!\n", runtime.GOARCH) }

让我们创建一个 Dockerfile 来容器化这个应用

$ cat Dockerfile FROM golang:alpine AS builder RUN mkdir /app ADD . /app/ WORKDIR /app RUN go build -o hello .  FROM alpine RUN mkdir /app WORKDIR /app COPY --from=builder /app/hello . CMD ["./hello"]

这是一个多阶段 Dockerfile,通过 Go 编译器构建我们的应用程序,然后将构建出来的二进制程序使用 Alpine Linux  镜像创建成最小镜像。

现在,让我们使用 buildx 来构建一个支持 arm、arm64 和 amd64 架构的多架构镜像,并一次性推送到 Docker Hub:

$ docker buildx build -t mirailabs/hello-arch --platform=linux/arm,linux/arm64,linux/amd64 . --push

是的,就是这样。现在 Docker Hub 上我们有了 支持 arm、arm64 和 amd64 架构的多架构 Docker 镜像。当我们运行  docker pull mirailabs/hello-arch 时,Docker 会根据机器的架构来获取匹配的镜像。

如果读者要问 buildx 是如何实现这个魔法的?好吧,在命令的背后,buildx 使用 QEMU 和 binfmt_misc 创建了三个 Docker  镜像(arm、arm64 和 amd64 架构每个创建一个)。当构建完成后,Docker  会创建一个清单,其中包含这三个镜像以及他们对应的架构。换句话说,“多架构镜像”实际上是一个清单,列举了每个架构对应的镜像。

步骤 5:测试多架构镜像

让我们来快速测试下多架构镜像,以确保它们都能够正常工作。由于我们已经设置了 binfmt_misc,因此在开发机器上已经能够执行任何架构的镜像了。

首先,列出每个镜像的散列值:

$ docker buildx imagetools inspect mirailabs/hello-arch Name:      docker.io/mirailabs/hello-arch:latest MediaType: application/vnd.docker.distribution.manifest.list.v2+json Digest:    sha256:bbb246e520a23e41b0c6d38b933eece68a8407eede054994cff43c9575edce96  Manifests:   Name:      docker.io/mirailabs/hello-arch:latest@sha256:5fb57946152d26e64c8303aa4626fe503cd5742dc13a3fabc1a890adfc2683df   MediaType: application/vnd.docker.distribution.manifest.v2+json   Platform:  linux/arm/v7    Name:      docker.io/mirailabs/hello-arch:latest@sha256:cc6e91101828fa4e464f7eddec3fa7cdc73089560cfcfe4af16ccc61743ac02b   MediaType: application/vnd.docker.distribution.manifest.v2+json   Platform:  linux/arm64    Name:      docker.io/mirailabs/hello-arch:latest@sha256:cd0b32276cdd5af510fb1df5c410f766e273fe63afe3cec5ff7da3f80f27985d   MediaType: application/vnd.docker.distribution.manifest.v2+json   Platform:  linux/amd64

有了这些散列值的帮助,我们可以逐一运行镜像,并观察其输出:

$ docker run --rm docker.io/mirailabs/hello-arch:latest@sha256:5fb57946152d26e64c8303aa4626fe503cd5742dc13a3fabc1a890adfc2683df Hello, arm!  $ docker run --rm docker.io/mirailabs/hello-arch:latest@sha256:cc6e91101828fa4e464f7eddec3fa7cdc73089560cfcfe4af16ccc61743ac02b Hello, arm64!  $ docker run --rm docker.io/mirailabs/hello-arch:latest@sha256:cd0b32276cdd5af510fb1df5c410f766e273fe63afe3cec5ff7da3f80f27985d Hello, amd64!

到此,关于“Docker镜像怎么做到一次构建,到处运行”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/144257.html

(0)

相关推荐

  • 猪宝宝小名,你孩子的名字是自己起的吗

    技术猪宝宝小名,你孩子的名字是自己起的吗是的,把我和孩子带坑里去了猪宝宝小名。尤其是我女儿的。生产前并不知道性别,所以就没先给孩子取名,出生后也才被告知要3天内取名,所以当时挺急的,女儿又是双方家庭的第一个孩子。此为背景

    生活 2021年10月30日
  • 五险一金指什么和社保,社保与五险一金有什么区别

    技术五险一金指什么和社保,社保与五险一金有什么区别社保与五险一金的区别1、社保和五险一金总体来说是概念不同五险一金指什么和社保:社保是社会保险的简称,是指养老保险、医疗保险、生育保险、失业保险、工伤保险五个险种。五险一金

    生活 2021年10月21日
  • Android Studio常用插件有哪些

    技术Android Studio常用插件有哪些小编给大家分享一下Android Studio常用插件有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了

    攻略 2021年11月23日
  • Ajax和WebSpherePortal设计有哪些注意事项

    技术Ajax和WebSpherePortal设计有哪些注意事项本篇内容介绍了“Ajax和WebSpherePortal设计有哪些注意事项”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大

    攻略 2021年11月14日
  • 不开心,有不开心的事情该怎么宣泄

    技术不开心,有不开心的事情该怎么宣泄生活中遇到不开心的事情怎样宣泄不开心:1,要放宽心态。一个人的心态很重要,人生不如意之事十之八九,所以要让自己的心态保持良好,放宽,不要去计较那些不开心的事情,让自己可以积极乐观的面对

    生活 2021年10月29日
  • Java程序开发环境配置图文的方法是什么

    技术Java程序开发环境配置图文的方法是什么本篇内容介绍了“Java程序开发环境配置图文的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大

    攻略 2021年11月19日