Docker编译多平台文件、构建多平台镜像并运行

news2025/1/12 9:37:42

参考官方文档:

  • Multi-stage
  • Multi-platform
  • Multi-platform images

文章目录

  • 方法
  • Buildx 设置
  • 使用QEMU仿真
    • 编译文件
    • 构建镜像
  • 使用交叉编译(cross-compilation)
    • 编译文件
    • 构建镜像
  • 在x86_64上运行arm64容器

方法

  如果在 x86_64/amd64 的平台上,想构建适用于多个平台的镜像,例如 linux/amd64linux/arm64,根据官方文档,有三种方法可以使用:

  1. QEMU
      使用 QEMU 模拟构建多平台映像是最简单的入门方法,但可能比本机构建慢得多,特别是对于编译、压缩或解压缩等计算量大的任务。因此如果条件允许的话,更推荐使用 Cross-compilation交叉编译)。但因为使用起来最简单,所以我在x86_64平台上构建arm64镜像并运行容器时用的是这个方法。
  2. Multiple native nodes
      使用多个本机节点可以为 QEMU 无法处理的更复杂的情况提供更好的支持,并且通常具有更好的性能。
  3. Cross-compilation
      交叉编译使多平台构建速度更快、用途更广泛,但必须要有相对应的编译器。

Buildx 设置

  在构建镜像时,是通过设置 --platform 参数来指定目标平台的。例如, linux/amd64linux/arm64darwin/amd64

  默认的构建驱动程序不支持并发多平台构建,一次只能针对一个平台进行构建(例如 docker build --platform=linux/amd64 )。
  如果想同时针对多个平台进行构建(例如 --platform=linux/amd64,linux/arm64 ),则需要创建构建器builder)。
  要使用不同的驱动程序,需要使用 Docker Buildx。 Buildx 是下一代构建客户端,它提供与 docker build 命令类似的用户体验,同时支持其他功能。

  例如创建一个使用docker-container作为驱动程序,名为container的新构建器:

docker buildx create --driver=docker-container --name=container

可以使用 docker buildx ls 命令列出可用的构建器。*标明了当前正在使用的构建器(在下面的示例中为default):

docker buildx ls                                                                                                                                                                                                                                                                                                
NAME/NODE    DRIVER/ENDPOINT             STATUS   BUILDKIT             PLATFORMS
container    docker-container                                          
  container0 unix:///var/run/docker.sock inactive                      
default *    docker                                                    
  default    default                     running  v0.11.7+d3e6c1360f6e linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386

从上面的输出中可以看到,container后的BUILDKITPLATFORMS为空,那么在第一次使用container构建镜像时,就会先下载相关文件,然后才会开始构建。

  也可以提前安装并在创建完成后马上启用构建器。需要用到tonistiigi/binfmt,之后还会自动下载moby/buildkit镜像。

如果电脑重启后在/proc/sys/fs/binfmt_misc中找不到qemu相关内容,那么还需要重新执行这条命令:

docker run --privileged --rm tonistiigi/binfmt --install all
docker buildx create --name mybuilder --bootstrap --use

结果如下:

docker buildx ls                                                                                                                                                                                                                                                                                                
NAME/NODE    DRIVER/ENDPOINT             STATUS   BUILDKIT             PLATFORMS
container    docker-container                                          
  container0 unix:///var/run/docker.sock inactive                      
mybuilder *  docker-container                                          
  mybuilder0 unix:///var/run/docker.sock running  v0.12.3              linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default      docker                                                    
  default    default                     running  v0.11.7+d3e6c1360f6e linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

使用QEMU仿真


上图为仿真构建过程。
 

  仿真构建时,需要指定构建器参数 --builder,以及平台参数 --platform

编译文件

  例如下面这条命令用于编译多平台二进制文件:

docker buildx build \
    --target=binaries \
    --output=bin \
    --builder=container \
    --platform=linux/amd64,linux/arm64,linux/arm/v7 .

示例Dockerfile详细内容见Github,需要下载整个仓库然后在仓库根目录执行该命令。

构建镜像

以下示例使用单个 Dockerfile 为多个平台构建了安装有 curl 的 Alpine 映像。

Dockerfile:

# syntax=docker/dockerfile:1
FROM alpine:3.16
RUN apk add curl

构建命令:

docker buildx build \
    --builder=mybuilder \
    --platform=linux/amd64,linux/arm64,linux/arm/v7 \
    --tag=<username>/<image>:latest \
    --push .

  其中 --push 表示构建完毕后推送到仓库。
  必须添加 --push--load 参数,否则会得到警告WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load。意思是构建结果只保存在缓存中,使用 --push 可以将镜像推送到远程仓库,使用 --load 可以将镜像保存在本地。
  需要注意的是,如果参数添加的是 --load 而不是 --push,并且--platform后面跟了多个平台,例如--platform=linux/amd64,linux/arm64,linux/arm/v7,那么还是会得到报错ERROR: docker exporter does not currently support exporting manifest lists,这是因为本地无法保存多个同名的镜像。所以如果要保存构建出的多个平台的镜像到本地,就得分多次执行命令,每次只在 --platform 后添加一个平台,并且每次的 --tag 后面的镜像名称都不同。
  例如为三个平台构建了镜像,就得分三次执行命令:

docker buildx build \
    --builder=mybuilder \
    --platform=linux/amd64 \
    --tag=<username>/<image>_amd64:latest \
    --load .
docker buildx build \
    --builder=mybuilder \
    --platform=linux/arm64 \
    --tag=<username>/<image>_arm64:latest \
    --load .
docker buildx build \
    --builder=mybuilder \
    --platform=linux/arm/v7 \
    --tag=<username>/<image>_arm_v7:latest \
    --load .

  可以使用 docker buildx imagetools 命令检查镜像,前提是镜像已推送到远程仓库。例如:

docker buildx imagetools inspect <username>/<image>:latest
Name:      docker.io/<username>/<image>:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:f3b552e65508d9203b46db507bb121f1b644e53a22f851185d8e53d873417c48

Manifests:
  Name:      docker.io/<username>/<image>:latest@sha256:71d7ecf3cd12d9a99e73ef448bf63ae12751fe3a436a007cb0969f0dc4184c8c
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64

  Name:      docker.io/<username>/<image>:latest@sha256:5ba4ceea65579fdd1181dfa103cc437d8e19d87239683cf5040e633211387ccf
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64

  Name:      docker.io/<username>/<image>:latest@sha256:29666fb23261b1f77ca284b69f9212d69fe5b517392dbdd4870391b7defcc116
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm/v7

  如果是使用 --load 保存到了本地,使用 docker image inspect 命令查看镜像。例如:

docker image inspect <username>/<image>_arm_v7

使用交叉编译(cross-compilation)

在这里插入图片描述
https://docs.docker.com/build/guide/images/cross-compilation.png

上图为交叉编译构建过程。
 

编译文件

由于Go语言的编译器支持在编译时通过使用 GOOSGOARCH 环境变量来进行交叉编译,因此可以通过Docker自动将 --platform 的参数解析为构建参数TARGETPLATFORMTARGETOSTARGETARCH,并在Dockerfile中赋值给环境变量,来实现交叉编译。

示例Dockerfile详细内容见Github或官网文档,需要下载整个仓库然后在仓库根目录执行该命令。

构建镜像

Dockerfile示例:

# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log
FROM alpine
COPY --from=build /log /log

在x86_64上运行arm64容器

  先执行这条命令,确保/proc/sys/fs/binfmt_misc有qemu相关内容:

docker run --privileged --rm tonistiigi/binfmt --install all

  接下来以运行arm64版本的ubuntu 18.04为例:

  1. 下载镜像
docker pull --platform=linux/arm64 ubuntu:18.04 
  1. 运行
docker run --rm -it ubuntu:18.04

忽略警告WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested

  1. 查看版本等相关信息
uname -a

  hello-world镜像同理:

docker run --rm --platform=linux/arm64 hello-world
docker run --rm --platform=linux/arm64 hello-world                         

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1401642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker 操作之数据卷挂载【云原生】

文章目录 1. 镜像1.1 基本命令1.2 案例练习 2. 容器2.1 基本命令2.2 Nginx 案例2.3 Redis 案例 3. 数据卷3.1 基本命令3.2 Nginx 案例3.3 MySQL 案例 1. 镜像 镜像命令一般分两部分组成&#xff1a;repository:tag。比如 mysql:5.7&#xff0c;表示名称加版本。 在没有指定 t…

一文掌握Python所有常见的循环用法

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 循环是编程中的重要概念&#xff0c;它允许我们重复执行一组操作&#xff0c;直到满足某个条件。Python提供了多种类型的循环&#xff0c;以适应不同的需求和场景。本文将详细介绍Python中所有常见的循环用法&am…

MySQL下对[表]的操作数据类型

目录 表的操作 创建表&#xff1a; 查看表结构&#xff1a; 修改表&#xff1a; 删除表&#xff1a; 数据类型 数据类型分类&#xff1a; 数值类型&#xff1a; tinyint类型越界测试&#xff1a; bit类型&#xff1a; 小数类型&#xff1a; 字符串类型&#xff1a; …

JAVA中 Lambda 方法引用 算法

算法和数据结构 一、Arrays类 接下来学习的类叫做Arrays&#xff0c;其实Arrays并不是重点&#xff0c;但是我们通过Arrays这个类的学习有助于我们理解下一个知识点Lambda的学习。所以我们这里先学习Arrays&#xff0c;再通过Arrays来学习Lamdba这样学习会更丝滑一些_. 1.1 …

【Qt Quick 项目(第一集Qt Quick UI 项目项目创建)】

# Qt Quick 项目 到底什么是Qt Qml、什么是Qt Quick、QtQuick应用程序与Qt Widget程序有何区别,为了让读者在学习QML之前有一个整体认识,这里先介绍几个Quick项目。 01 Qt Quick UI 项目

Java8的Stream最佳实践

从这一篇文章开始&#xff0c;我们会由浅入深&#xff0c;全面的学习stream API的最佳实践&#xff08;结合我的使用经验&#xff09;&#xff0c;本想一篇写完&#xff0c;但写着写着发现需要写的内容太多了&#xff0c;所以分成一个系列慢慢来说。给大家分享我的经验的同时&a…

【博士每天一篇论文-技术综述】Machine Learning With Echo State Networks 一篇系统讲解ESN知识的五星文章

阅读时间&#xff1a;2023-11-21 1 介绍 年份&#xff1a;2020 作者&#xff1a;徐元超&#xff0c;曼尼托巴大学 期刊&#xff1a; 无 引用量&#xff1a;无 这篇文章是一篇技术报告&#xff0c;从递归神经网络&#xff08;RNNs&#xff09;引入到回声状态网络&#xff08;…

JavaScript基础之JavaScript简介(什么是JavaScript?)

JavaScript简介 JavaScript&#xff0c;通常被缩写为JS&#xff0c;是一种轻量级、跨平台、单线程、解释编译的编程语言。它也被称为网页脚本语言。它以网页开发而闻名&#xff0c;许多非浏览器环境也使用它。 JavaScript是一种弱类型语言。JavaScript可用于客户端开发以及服…

shell编程学习

shell编程学习 变量的高级用法变量替换字符串处理获取字符索引获取子串长度抽取字符串中的子串 案例测试 变量的高级用法 变量替换 ##变量替换&#xff08;贪婪&#xff0c;从前往后匹配&#xff0c;匹配到进行删除&#xff09; test1I love you,you love me echo $test1 han…

Java研学-spring框架(一)

一 概述 1 介绍 Spring框架是一个开源的Java EE应用程序框架&#xff0c;旨在简化Java企业级应用的开发难度和开发周期&#xff0c;主要通过控制反转&#xff08;IoC&#xff09;和面向切面编程&#xff08;AOP&#xff09;等技术实现。   容器&#xff08;Container&#x…

【CVE-2022-22733漏洞复现】

Apache ShardingSphere ElasticJob-UI漏洞 漏洞编号:CVE-2022-22733 文档说明 本文作者:SwBack 创作时间:2024/1/21 19:19:19 知乎:https://www.zhihu.com/people/back-88-87 CSDN:https://blog.csdn.net/qq_30817059 百度搜索: SwBack漏洞描述 Apache ShardingSphere Elast…

Python基础第二篇(Python基础语法)

文章目录 一、字面量二、注释三、变量四、数据类型五、数据类型转换六、标识符七、运算符八、字符串扩展内容&#xff08;1&#xff09;字符串定义&#xff08;2&#xff09;字符串拼接、&#xff08;3&#xff09;字符串格式化&#xff08;4&#xff09;字符串格式化的精度控制…

上位机图像处理和嵌入式模块部署(开篇)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 图像处理是现实生活当中很实用的一门技术。工业上一般采用的是机器视觉&#xff0c;以传统算法和光源控制为主&#xff0c;部分采用了深度学习技术…

MySQL的下载、安装、配置、登录,配置(图+文)(超级详细)

一、 软件的下载 1. 下载地址 官网&#xff1a; https://www.mysql.com 2. 打开官网&#xff0c;点击 DOWNLOADS 然后&#xff0c;点击 MySQL Community(GPL) Downloads 3. 点击 MySQL Community Server 4. 在 General Availability(GA) Releases 中选择适合的版本 …

【C语言基础篇】结构控制(下)转向语句break、continue、goto、return

文章目录 一、break语句 1. break在 while 循环中 2. break在 for 循环中 3. break在 do…while 循环中 4. break在 switch 语句中 5. break 总结 二、continue语句 1. continue在 while 循环中 2. continue在 for 循环中 3. continue在 do...while 循环中 4. con…

Kubernetes网络模型概述

Kubernetes网络模型设计的一个基础原则是&#xff1a;每个Pod都拥有一个独立的IP地址&#xff0c;并假定所有Pod都在一个可以直接连通的、扁平的网络空间中。所以不管这些Pod是否运行在同一个Node中&#xff0c;都要求它们可以直接通过对方的IP进行访问。由于Kubernetes的网络模…

C++泛型编程-类模板的项目实战实现基础的Vector的编写

请设计一个数组模板类&#xff08; Vector &#xff09;&#xff0c;完成对 int 、 char 、 float 、 double 以 及任意的自定义类等类型元素进行管理。 需求 a. 实现构造函数 b. 实现拷贝构造函数 c. 实现 cout << 操作 d. 实现下标访问符 [] 的重载操作 …

中仕教育:应届生可以考军队文职吗?有什么要求?

军队文职&#xff0c;涵盖了各个领域&#xff0c;包括行政、管理、人力资源、后勤等工作岗位&#xff0c;作为国家公务员的一种类型&#xff0c;军队文职同样享有稳定的工作和待遇。 虽然军队文职对所有符合条件的人开放&#xff0c;但对于应届生来说&#xff0c;还需满足以下…

企业Oracle1 数据库管理

Oracle的安装 一、基础表的创建 1.1 切换到scott用户 用sys 账户 登录 解锁scott账户 alter user scott account unlock;conn scott/tiger;发现并不存在scott账户&#xff0c;自己创建一个&#xff1f; 查找资料后发现&#xff0c;scott用户的脚本需要自己执行一下 C:\ap…

Spring:StopWatch

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、输出总耗时 二、输出所有任务的耗时和占比 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、输出总耗时 public void stopWatc…