是一种流行的部署工具,使我们能够打包和运行应用程序。由于采用率很高,需要根据不同的要求扩展功能。因此,为了实现这一目标,第三方使用了 插件。

例如,如果我们希望数据能够跨不同主机保存数据,我们可以使用卷插件。另一个常用的插件是 。它通过使用 构建器扩展了镜像的构建能力。因此镜像文件格式,通过该插件,我们可以为不同的平台和架构构建镜像。此外,它还支持具有自定义上下文的并行多阶段构建。

默认的 build命令无法完成跨平台构建任务,我们需要为命令行安装插件扩展其功能。能够使用由Moby 提供的构建镜像额外特性,它能够创建多个 实例,在多个节点并行地执行构建任务,以及跨平台构建。

启用

首先,为了运行 ,我们需要安装 。 支持从 .00 开始提供。

首先检查我们的 版本:

docker --version
Docker version 19.03.8, build afacb8b

接下来,我们通过设置环境变量来启用实验功能:

export DOCKER_CLI_EXPERIMENTAL=enabled

为了确保我们的设置在会话后保留,我们将变量添加到Bash的$HOME/.中。完成后,我们现在应该可以访问 了:

$ docker buildx

Usage:  docker buildx COMMAND

Build with BuildKit

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
  inspect     Inspect current builder instance
  ls          List builder instances
  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.

这显示了常用命令以及每个命令的语法。

使用进行构建的方法如下:

docker buildx build .

和 build命令的使用体验基本一致,还支持build常用的选项如-t、-f等。

新建 实例

通过 实例对象来管理构建配置和节点,命令行将构建任务发送至 实例,再由 指派给符合条件的节点执行。我们可以基于同一个服务程序创建多个 实例,提供给不同的项目使用以隔离各个项目的配置,也可以为一组远程节点创建一个 实例组成构建阵列,并在不同阵列之间快速切换。

使用 命令可以创建 实例,这将以当前使用的 服务为节点创建一个新的 实例。要使用一个远程节点,可以在创建示例时通过环境变量指定远程端口或提前切换到远程节点的 。

创建实例:

# 创建一个名为 "multi-platform-builder" 的 Buildx 构建器,并启用它,以便支持多个平台的容器镜像构建
$ sudo docker buildx create --use --platform=linux/arm64,linux/amd64 --name multi-platform-builder
multi-platform-builder

# 检查和验证 Docker Buildx 构建器的命令,以确保它已正确设置和准备好进行构建任务
$ sudo docker buildx inspect --bootstrap
[+] Building 15.2s (1/1) FINISHED                                                                                 
 => [internal] booting buildkit                                                                                   
 => => pulling image moby/buildkit:buildx-stable-1                                                                
 => => creating container buildx_buildkit_multi-platform-builder0                                                 
Name:   multi-platform-builder
Driver: docker-container

Nodes:
Name:      multi-platform-builder0
Endpoint:  unix:///var/run/docker.sock
Status:    running
Platforms: linux/arm64*, linux/amd64*, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386

使用构建多架构镜像

可以执行所有构建功能。因此,我们可以轻松地运行并执行它们。例如,指定目标平台、构建缓存和输出配置。除此之外,还提供了额外的功能。

首先,能够同时为多个平台构建镜像。其次,能够在构建过程中自定义输入、参数或变量。

源代码和

下面将以一个简单的 Go 项目作为示例,假设示例程序文件main.go内容如下:

package main

import "fmt"

func main() {
    fmt.Println("hello world")
}

定义构建过程的 如下:

FROM golang:1.17 as builder
WORKDIR /opt/app
COPY . .
RUN go mod init main && go build -o example


FROM alpine:latest
WORKDIR /opt/app
COPY --from=builder /opt/app/example ./example

构建过程分为两个阶段:

执行跨平台构建

$ docker buildx build -f ./Dockerfile-4 --platform linux/amd64,linux/arm64 -t fly190712/example:v2 --push .
                                                                             
[+] Building 80.6s (27/27) FINISHED                                                                              
 => [internal] load build definition from Dockerfile-4                                                      0.0s
 => => transferring dockerfile: 337B                                                                        0.0s
 => resolve image config for docker.io/docker/dockerfile:1                                                 10.5s
 => [auth] docker/dockerfile:pull token for registry-1.docker.io                                            0.0s
 => CACHED docker-image://docker.io/docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab2021  0.0s
 => => resolve docker.io/docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032e  0.0s
 => [linux/amd64 internal] load metadata for docker.io/library/golang:1.17                                  2.6s
 => [linux/arm64 internal] load metadata for docker.io/library/alpine:latest                                5.4s
 => [linux/amd64 internal] load metadata for docker.io/library/alpine:latest                                5.1s
 => [linux/arm64 internal] load metadata for docker.io/library/golang:1.17                                  4.5s
 => [auth] library/alpine:pull token for registry-1.docker.io                                               0.0s
 => [internal] load .dockerignore                                                                           0.0s
 => => transferring context: 2B                                                                             0.0s
 => [linux/arm64 builder 1/4] FROM docker.io/library/golang:1.17@sha256:87262e4a4c7db56158a80a18fefdc4fee5  0.0s
...
 => [linux/amd64 stage-1 1/3] FROM docker.io/library/alpine:latest@sha256:7144f7bab3d4c2648d7e59409f15ec52  0.0s
...
 => [internal] load build context                                                                           0.0s
 => => transferring context: 1.32kB                                                                         0.0s
 => [linux/amd64 builder 1/4] FROM docker.io/library/golang:1.17@sha256:87262e4a4c7db56158a80a18fefdc4fee5  0.0s
 ...                                                                  0.0s
 => [linux/amd64 builder 4/4] RUN go mod init main && go build -o example                                   0.7s
 => [linux/arm64 builder 4/4] RUN go mod init main && go build -o example                                   3.1s

 => exporting to image                                                                                     13.0s
                                                                                    10.1s
 => => pushing manifest for docker.io/fly190712/example:v2@sha256:507132b53d6c71d36dcedb916c18ceee9a742059  2.7s
 => [auth] fly190712/example:pull,push token for registry-1.docker.io                                       0.0s

注意:构建完成后,镜像在 中是查不到的,因为这个镜像仅位于 缓存中。我们这里使用--push标志可用于直接将镜像推送到 。

多架构镜像

除此之外, build支持丰富的输出行为,通过--=[PATH,-,type=TYPE[,KEY=VALUE]选项可以指定构建结果的输出类型和路径等,常用的输出类型有以下几种:

我们执行如下 build命令:

$ docker buildx build -f ./Dockerfile-4 --platform linux/amd64,linux/arm64 -t fly190712/example:v2 -o type=registry .

该命令将在当前目录同时构建linux/amd64、linux/arm64和linux/arm三种平台的镜像,并将输出结果直接推送到远程的阿里云镜像仓库中。

构建过程可拆解如下:

1.将构建上下文传输给 实例。

2. 为命令行--选项指定的每一个目标平台构建镜像,包括拉取基础镜像和执行构建步骤。

3. 导出构建结果,镜像文件层被推送到远程仓库。

4. 生成一个清单 JSON 文件,并将其作为镜像标签推送给远程仓库。

更重要的补充构建驱动

实例通过两种方式来执行构建任务,两种执行方式被称为使用不同的「驱动」:

驱动无法使用一小部分的特性(如在一次运行中同时构建多个平台镜像),此外在镜像的默认输出格式上也有所区别:驱动默认将构建结果以 镜像格式直接输出到的镜像目录(通常是/var/lib/),之后执行 命令可以列出所输出的镜像;

而 则需要通过--选项指定输出格式为镜像或其他格式。

为了一次性构建多个平台的镜像,本文使用 作为默认的 实例驱动。

解决 ERROR list

如果你使用了较新版本的 (>=0.10) 和 (>=0.11) 以及较旧版本的镜像仓库镜像文件格式,在构建跨平台镜像时可能会遇到构建成功但推送失败的问题,报错如下:

 => => pushing layers                                                                                                                                          12.3s
 => => pushing manifest for registry.xxx.com/xxx/postgres-vb                                                                                          0.9s
 => [auth] xxx/postgres-vb:pull,push token for registry.xxx.com                                                                                       0.0s
 => ERROR merging manifest list registry.xxx.com/xxx/postgres-vb:v1.2.0

这是因为新版本默认开启了Build 功能以增强供应链安全,但同时带来了兼容性问题。如果你并不需要,可添加如下 build 选项禁用它以解决该问题:

docker buildx build --sbom=false --provenance=false

的跨平台构建策略

根据构建节点和目标程序语言不同,**支持以下三种跨平台构建策略**:

1.通过QEMU 的用户态模式创建轻量级的虚拟机,在虚拟机系统中构建镜像。

2.在一个 实例中加入多个不同目标平台的节点,通过原生节点构建对应平台镜像。

3.分阶段构建并且交叉编译到不同的目标架构。

QEMU 通常用于模拟完整的操作系统,它还可以通过用户态模式运行:以在宿主机系统中注册一个二进制转换处理程序,并在程序运行时动态翻译二进制文件,根据需要将系统调用从目标 CPU 架构转换为当前系统的 CPU 架构。最终的效果就像在一个虚拟机中运行目标 CPU 架构的二进制文件。

内置了 QEMU 支持,其他满足运行要求的平台可通过以下方式安装:

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

这种方式不需要对已有的 做任何修改,实现的成本很低,但显而易见效率并不高。

将不同系统架构的原生节点添加到 实例中可以为跨平台编译带来更好的支持,而且效率更高,但需要有足够的基础设施支持。

如果构建项目所使用的程序语言支持交叉编译(如 C 和 Go),可以利用 提供的分阶段构建特性:首先在和构建节点相同的架构中编译出目标架构的二进制文件,再将这些二进制文件复制到目标架构的另一镜像中。

快速加K8s学习交流群,与大佬共卷!

镜像文件格式_镜像文件的格式_镜像格式文件是什么

扫码加我微信,进群和大佬们零距


限时特惠:
本站持续每日更新海量各大内部创业课程,一年会员仅需要98元,全站资源免费下载
点击查看详情

站长微信:Jiucxh

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注