1. 概述

Docker 是一个流行的部署工具,它使我们能够打包并运行应用程序。由于其广泛采用,经常需要根据不同的需求扩展功能。因此,为了实现这一点,一些部署会使用 Docker 插件。例如,如果我们要在不同主机上持久化数据,我们会使用存储卷插件。另一个常用插件是 Docker buildx。它通过使用 BuildKit 建设器扩展了 图像 的构建能力。因此,借助此插件,我们可以为不同的平台和架构构建图像。此外,它支持带有自定义上下文的并行多阶段构建。

本文档将介绍 Docker buildx 的入门知识。

2. 安装 buildx

首先,对于 buildx 能够运行,我们需要安装 Docker。Docker buildx 支持从 Docker 引擎 19.00 版本开始。

2.1. 检查 Docker 版本

让我们首先检查我们的 Docker 版本:

$ docker --version
Docker version 19.03.8, build afacb8b

在这种情况下,我们支持 buildx

2.2. 启用实验性功能

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

$ export DOCKER_CLI_EXPERIMENTAL=enabled

为了确保设置在会话结束后仍然有效,我们将其添加到 $HOME/.bashrc 中以适用于 Bash。

2.3. 验证 buildx

有了这些设置,我们现在应该可以访问 buildx

$ 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.

输出显示了常见的子命令及其语法。

2.4. 故障排查

有时,尽管一切准备就绪,但在执行 buildxdocker 子命令时仍可能会出现错误:

$ docker buildx build .
docker: 'buildx' is not a docker command.
See 'docker --help'

即使我们似乎拥有 Docker 19 及以上版本,这种情况也可能发生。通常,这种问题的原因是使用了 docker.io 包。

无论如何,更正此问题的主要方法之一是安装 docker-buildx 包。例如,让我们使用 APT:

$ apt install docker-buildx

或者 如果我们使用官方 Docker 仓库 (https://docs.docker.com/engine/install/) ,则安装 docker-buildx-plugin

$ apt install docker-buildx-plugin

通常,后者是更好的方法,因为它得到官方支持。

要找出可用的包(如果有),我们也可以使用本地包管理器:

$ apt list --installed | grep buildx

如果所有其他方法都失败, 我们还可以重启 Docker 主机作为潜在的修复方法

3. 使用 buildx 构建

buildx 执行所有 Docker build 能力。因此,我们可以像 build 一样执行它们。例如,指定目标平台、构建缓存和输出配置。除此之外,buildx 提供额外的功能。

主要的是,buildx 提供了同时为多个平台构建图像的能力。此外,我们可以在单个 dockerfile 内进行多阶段构建,以构建较小的图像。最后,build**x 具有在构建过程中自定义输入、参数或变量的能力。

让我们通过创建实例来深入研究一个示例:

$ docker buildx create --name ourbuilder
ourbuilder

这创建了一个名为 ourbuilder 的构建实例。

接下来,我们将它设置为活动目录:

$ docker buildx use ourbuilder

之后,让我们创建一个 dockerfile 来运行简单的 node 应用程序:

# Base image
FROM node:14-alpine

# Set working directory
WORKDIR /app

# Copy application files
COPY . .

# Install dependencies
RUN npm install --production

# Expose the port
EXPOSE 3000

# Start the application
CMD ["node", "app.js"]

在这里,我们使用 node.js 基础图像,并将工作目录设置为 /app。然后,我们将 app 文件复制到容器中。最后,我们安装所有依赖项,暴露端口 3000 并启动应用

$ docker buildx build --platform linux/amd64,linux/arm64 -t ourapp:latest .
time="2023-06-01T07:13:20+03:00" level=warning msg="No output specified for 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"
#1 [internal] booting buildkit
#1 pulling image moby/buildkit:buildx-stable-1
#1 pulling image moby/buildkit:buildx-stable-1 73.2s done
#1 creating container buildx_buildkit_ourbuilder0
#1 creating container buildx_buildkit_ourbuilder0 2.1s done
#1 DONE 75.4s

#3 [internal] load .dockerignore
#3 transferring context: 0.0s
#3 transferring context: 2B 0.1s done
#3 DONE 0.3s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 294B 0.0s done
#2 DONE 0.4s

#4 [linux/amd64 internal] load metadata for docker.io/library/node:14-alpin...
#4 DONE 4.7s
.... truncated ..... 

我们使用 –platform 标志指定目标平台。在这种情况下,我们针对 x86(Linux/amd64)和 ARM(Linux/arm64)架构。此外,我们提供标签 -t ourapp:latest,以便图像包含名称 ourapp 和最新标签。句点表示构建上下文,即当前目录。

Docker buildx 自动处理多平台构建,为每个目标架构生成单独的图像。

注意: 当使用 buildx 多个平台时,除非指定,否则图像不会被加载到 Docker 中。要将图像加载到 Docker 中,请使用 --load 标志:

$ docker buildx build --load -t ourapp:latest .

设置展示了 BuildX 在有效地管理构建方面的灵活性。

4. 总结

在本文档中,我们探讨了 Docker buildx 这个扩展 Docker 图像构建和管理能力的工具。它简化了流程,支持并行构建、自定义构建上下文和多阶段构建。