首页 > 其他分享 >docker构建跨平台应用(x86,arm)

docker构建跨平台应用(x86,arm)

时间:2024-01-22 10:57:49浏览次数:31  
标签:x86 -- 跨平台 linux 镜像 docker hello

1.直接从官方仓库拉去指定平台的镜像

docker pull --platform=<plartform> <image-name>:<tag>

  例:

docker pull --platform=arm64 nginx:latest

2.打包指定平台的镜像

安装并使用 buildx

 

使用 builder 构建跨平台镜像

现在一些准备工作已经就绪,我们终于可以使用 builder 构建跨平台镜像了。

这里以一个 Go 程序为例,来演示如何构建跨平台镜像。

hello.go 程序如下:

package main

import (
    "fmt"
    "runtime"
)

func main() {
    fmt.Printf("Hello, %s/%s!\n", runtime.GOOS, runtime.GOARCH)
}

这个程序非常简单,执行后打印 Hello, 操作系统/CPU 架构

Go 程序还需要一个 go.mod 文件:

module hello

go 1.20

编写 Dockerfile 内容如下:

FROM golang:1.20-alpine AS builder
WORKDIR /app
ADD . .
RUN go build -o hello .

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/hello .
CMD ["./hello"]

这是一个普通的 Dockerfile 文件,为了减小镜像大小,使用了多阶段构建。它跟构建仅支持当前平台的镜像所使用的 Dockerfile 没什么两样。

$ ls
Dockerfile go.mod     hello.go

以上三个文件需要放在同一个目录下,然后就可以在这个目录下使用 docker buildx 来构建跨平台镜像了。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go .

docker buildx build 语法跟 docker build 一样,--platform 参数表示构建镜像的目标平台,-t 表示镜像的 Tag,. 表示上下文为当前目录。

唯一不同的是对 --platform 参数的支持,docker build 的 --platform 参数只支持传递一个平台信息,如 --platform linux/arm64,也就是一次只能构建单个平台的镜像。

而使用 docker buildx build 构建镜像则支持同时传递多个平台信息,中间使用英文逗号分隔,这样就实现了只用一条命令便可以构建跨平台镜像的功能。

执行以上命令后,我们将会得到一条警告:

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

这条警告提示我们没有为 docker-container 驱动程序指定输出,生成结果将只会保留在构建缓存中,使用 --push 可以将镜像推送到 Docker Hub 远程仓库,使用 --load 可以将镜像保存在本地。

这是因为我们新创建的 mybuilder 是启动了一个容器来运行 BuildKit,它并不能直接将构建好的跨平台镜像输出到本机或推送到远程,必须要用户来手动指定输出位置。

我们可以尝试指定 --load 将镜像保存的本地主机。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --load
[+] Building 0.0s (0/0)
ERROR: docker exporter does not currently support exporting manifest lists

结果会得到一条错误日志。看来它并不支持直接将跨平台镜像输出到本机,这其实是因为传递了多个 --platform 的关系,如果 --platform 只传递了一个平台,则可以使用 --load 将构建好的镜像输出到本机。

那么我们就只能通过 --push 参数将跨平台镜像推送到远程仓库了。不过在此之前需要确保使用 docker login 完成登录。

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-go . --push

现在登录 Docker Hub 就可以看见推送上来的跨平台镜像了。

我们也可以使用 imagetools 来检查跨平台镜像的 manifest 信息。

$ docker buildx imagetools inspect jianghushinian/hello-go
Name:      docker.io/jianghushinian/hello-go:latest
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest:    sha256:51199dadfc55b23d6ab5cfd2d67e38edd513a707273b1b8b554985ff562104db

Manifests:
  Name:      docker.io/jianghushinian/hello-go:latest@sha256:8032a6f23f3bd3050852e77b6e4a4d0a705dfd710fb63bc4c3dc9d5e01c8e9a6
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/arm64

  Name:      docker.io/jianghushinian/hello-go:latest@sha256:fd46fd7e93c7deef5ad8496c2cf08c266bac42ac77f1e444e83d4f79d58441ba
  MediaType: application/vnd.docker.distribution.manifest.v2+json
  Platform:  linux/amd64

可以看到,这个跨平台镜像包含了两个目标平台的镜像,分别是 linux/arm64 和 linux/amd64

我们分别在 Apple M2 芯片平台和 Linux x86 平台来启动这个 Docker 镜像看下输出结果。

$ docker run --rm jianghushinian/hello-go
Hello, linux/arm64!
$ docker run --rm jianghushinian/hello-go
Hello, linux/amd64!

至此,我们使用 builder 完成了跨平台镜像的构建。

使用交叉编译

以上演示的构建跨平台镜像过程就是利用 QEMU 的能力,因为 Go 语言的交叉编译非常简单,所以我们再来演示一下如何使用交叉编译来构建跨平台镜像。

我们只需要对 Dockerfile 文件进行修改:

FROM --platform=$BUILDPLATFORM golang:1.20-alpine AS builder
ARG TARGETOS
ARG TARGETARCH
WORKDIR /app
ADD . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o hello .

FROM --platform=$TARGETPLATFORM alpine:latest
WORKDIR /app
COPY --from=builder /app/hello .
CMD ["./hello"]

其中 BUILDPLATFORMTARGETOSTARGETARCHTARGETPLATFORM 四个变量是 BuildKit 提供的全局变量,分别表示构建镜像所在平台、操作系统、架构、构建镜像的目标平台。

在构建镜像时,BuildKit 会将当前所在平台信息传递给 Dockerfile 中的 BUILDPLATFORM 参数(如 linux/arm64)。

通过 --platform 参数传递的 linux/arm64,linux/amd64 镜像目标平台列表会依次传递给 TARGETPLATFORM 变量。

而 TARGETOSTARGETARCH 两个变量在使用时则需要先通过 ARG 进行声明,BuildKit 会自动为其赋值。

在 Go 程序进行编译时,可以通过 GOOS 环境变量指定目标操作系统,通过 GOARCH 环境变量指定目标架构。

所以这个 Dockerfile 所表示的含义是:首先拉取当前构建镜像所在平台的 golang 镜像,然后使用交叉编译构建目标平台的 Go 程序,最后将构建好的 Go 程序复制到目标平台的 alpine 镜像。

最终我们会通过交叉编译得到一个跨平台镜像。

笔记:通过 FROM --platform=$BUILDPLATFORM image 可以拉取指定平台的镜像,由此我们可以知道,其实 golang 和 alpine 镜像都是支持跨平台的。

构建镜像命令不变:

$ docker buildx build --platform linux/arm64,linux/amd64 -t jianghushinian/hello-cross-go . --push

启动镜像后输出结果不变:

$ docker run --rm jianghushinian/hello-cross-go
Hello, linux/arm64!
$ docker run --rm jianghushinian/hello-cross-go
Hello, linux/amd64!

至此,我们利用 Go 语言的交叉编译完成了跨平台镜像的构建。

平台相关的全局变量

关于上面提到的几个全局变量,BuildKit 后端预定义了一组 ARG 全局变量(共 8 个)可供使用,其定义和说明如下:

变量说明
TARGETPLATFORM 构建镜像的目标平台,如:linux/amd64,linux/arm/v7,windows/amd64。
TARGETOS TARGETPLATFORM 的操作系统,如:linux、windows。
TARGETARCH TARGETPLATFORM 的架构类型,如:amd64、arm。
TARGETVARIANT TARGETPLATFORM 的变体,如:v7。
BUILDPLATFORM 执行构建所在的节点平台。
BUILDOS BUILDPLATFORM 的操作系统。
BUILDARCH BUILDPLATFORM 的架构类型。
BUILDVARIANT BUILDPLATFORM 的变体。

使用示例如下:

# 这里可以直接使用 TARGETPLATFORM 变量
FROM --platform=$TARGETPLATFORM alpine

# 稍后的 RUN 命令想要使用变量必须提前用 ARG 进行声明
ARG TARGETPLATFORM

RUN echo "I'm building for $TARGETPLATFORM"

删除 builder

我们已经实现了使用 builder 构建跨平台镜像。如果现在你想要恢复环境,删除新建的 builder。则可以使用 docker buildx rm mybuilder 命令来完成。

$ docker buildx rm mybuilder
mybuilder removed

跟随 mybuilder 启动的 buildx_buildkit_mybuilder0 容器也会随之被删除。

现在再使用 docker buildx ls 命令查看构建器列表,已经恢复成原来的样子了。

$ docker buildx ls
NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default *       docker
  default       default         running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux   running 20.10.21 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

功能清单

除了前文介绍的几个 buildx 常用命令,更多功能可以通过 --help 参数进行查看。

$ docker buildx --help

Usage:  docker buildx [OPTIONS] COMMAND

Extended build capabilities with BuildKit

Options:
      --builder string   Override the configured builder instance

Management Commands:
  imagetools  Commands to work on images in registry

Commands:
  bake        Build from a file
  build       Start a build
  create      Create a new builder instance
  du          Disk usage
  inspect     Inspect current builder instance
  ls          List builder instances
  prune       Remove build cache
  rm          Remove a builder instance
  stop        Stop builder instance
  use         Set the current builder instance
  version     Show buildx version information

Run 'docker buildx COMMAND --help' for more information on a command.

如 stoprm 可以管理 builder 的生命周期。每条子命令又可以使用 docker buildx COMMAND --help 方式查看使用帮助,感兴趣的同学可以自行学习。

总结

标签:x86,--,跨平台,linux,镜像,docker,hello
From: https://www.cnblogs.com/databank/p/17979533

相关文章

  • 企业级GitLab在Docker部署使用
    一、部署gitlab这里使用的是Centos8,安装Docker环境,这里不说了,参考:https://www.cnblogs.com/wei325/p/15139701.htmlgitlab有ce版和ee版,ce版为免费版本;ee版为企业版本,需要收费;这里用ce版。1)拉取Gitlab镜像dockerpullgitlab/gitlab-ce  2)启动Docker先建3个目......
  • Avalonia跨平台入门
    Avalonia跨平台入门第一篇Avalonia跨平台入门第二篇Avalonia跨平台入门第三篇之PopupAvalonia跨平台入门第四篇之Popup在uos下问题Avalonia跨平台入门第五篇之ListBox多选Avalonia跨平台入门第六篇之Grid动态分割Avalonia跨平台入门第七篇之RadioButton的模板Avalonia跨平台入门第......
  • Docker Compose学习路线
    DockerCompose是一种用于定义和运行多容器Docker应用程序的工具。以下是一份DockerCompose的学习路线:基础知识:了解DockerCompose的概念和用途熟悉DockerCompose的基本语法和命令环境搭建:安装Docker和DockerCompose配置DockerCompose环境变量基本概念和配置:配置文件:DockerCom......
  • Docker学习路线
    Docker是一款开源的容器技术,它可以让开发者更轻松地打包、分发和运行应用程序。以下是学习Docker的推荐路径:基础知识了解Docker概念:容器、镜像、仓库、标签等了解Docker的架构:Docker客户端、Docker服务器(DockerDaemon)、Docker仓库了解Docker的工作原理:构建、拉取、运......
  • 使用docker容器部署zabbix5.4
    1.创建自定义网络dockernetworkcreate--subnet172.20.0.0/16--ip-range172.20.240.0/20zabbix-net2.运行MySQL服务dockerrun--namemysql-server-t\-eMYSQL_DATABASE="zabbix"\-eMYSQL_USER="zabbix"\-e......
  • Ubuntu一键安装/卸载docker和docker compose,可指定版本或安装最新版本。
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档@目录前言一、docker是什么?二、dockercompose是什么?三、安装步骤1.Ubuntu安装脚本2.生成脚本3.启动和验证四、卸载步骤1.Ubuntu卸载脚本2.保存文件后设置执行权限3.运行文件4.验证是否删除成功CentOS安装脚本卸载......
  • docker容器使用存储卷进行数据持久化
    1.将存储卷"test01"挂载到容器,若不存在则直接创建,默认权限为rw[root@centos201~]#dockercontainerrun-vtest01:/usr/share/nginx/html-d--nameweb01nginx:1.20.168f7609b7d72ba6e328605103cfb315b1a38aa2631ce69a576a228d1037300aa[root@centos201~]#[17:22:......
  • docker端口映射底层原理及常见写法
    1.将宿主机的所有IP地址的81端口映射到容器的80端口。默认使用tcp协议。[root@centos201~]#dockerrun-d-p81:80--nameweb01nginx:1.20.1e196b4a3a6b1b2bb7b97ccfe99479fd98786653c3799270aef98483b18a19301[root@centos201~]#2.指定IP地址进行端口映射[root@cent......
  • docker数据持久化(存储卷)
    1.查看现有的存储卷[root@centos201~]#dockervolumels#查看现有的存储卷DRIVERVOLUMENAME[root@centos201~]#2.创建随机(匿名)的存储卷[root@centos201~]#dockervolumecreate#创建随机(匿名)的存储卷050d2f963345d595c827551adc27ee48d61d482bfcf7c86......
  • docker容器管理
    1.查看容器[root@centos201~]#dockerps#查看现有的容器列表。CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES6aab26123615nginx:1.16"nginx-g'daemonof…"52secondsagoUp51seconds8......