如何解决 Docker Buildx 构建需要 1 个参数的问题

DockerDockerBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

Docker Buildx 扩展了标准的 Docker build 命令,增加了用于创建多架构镜像的增强功能。然而,用户在使用此工具时,经常会遇到 "docker buildx build requires exactly 1 argument" 错误。本教程将全面指导你理解 Docker Buildx,诊断这个常见错误,并实施有效的解决方案。

通过完成本实验,你将获得设置 Docker Buildx、创建 Docker 镜像、解决 "requires exactly 1 argument" 错误以及为多种架构构建镜像的实践经验。这些技能对于现代容器化应用程序的开发和部署至关重要。

设置 Docker Buildx

Docker Buildx 随 Docker 预安装,但需要在开始使用前进行正确设置。在这一步中,我们将验证 Docker 是否已安装,启用 Docker Buildx,并创建我们的第一个 builder 实例。

验证 Docker 安装

首先,让我们确认 Docker 已安装并在我们的系统上运行:

docker --version

你应该看到类似如下的输出:

Docker version 20.10.21, build baeda1f

这确认了 Docker 已安装并可以使用。

理解 Docker Buildx

Docker Buildx 是一个 CLI 插件,它使用 BuildKit 扩展了 Docker 的功能。它支持:

  • 同时为多个平台(如 AMD64、ARM64)构建镜像
  • 更有效的层缓存
  • 改进的构建性能
  • 高级构建功能

创建 Docker Buildx Builder

让我们创建一个新的 Docker Buildx builder 并使用它:

docker buildx create --name mybuilder --use

输出应该类似于:

mybuilder

现在,让我们验证我们的 builder 是否已创建并设置为默认值:

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/386

mybuilder 旁边的星号 (*) 表示它是当前活动的 builder。

检查 Builder

让我们检查一下 builder 的详细信息:

docker buildx inspect mybuilder

这将向你显示 builder 的配置,包括支持的平台及其当前状态。

现在我们已经成功设置了 Docker Buildx,我们准备好继续创建 Dockerfile 以与我们的 builder 一起使用。

创建一个简单的 Dockerfile 用于测试

在使用 Docker Buildx 构建镜像之前,我们需要创建一个简单的 Dockerfile。这将作为我们的测试用例,用于理解 "requires exactly 1 argument" 错误。

理解 Dockerfile

Dockerfile 是一个文本文件,其中包含构建 Docker 镜像的指令。它自动化了创建具有特定配置的容器的过程。

让我们为我们的项目创建一个目录:

mkdir -p ~/project/buildx-test
cd ~/project/buildx-test

创建一个基本的 Dockerfile

现在,让我们使用 nano 文本编辑器创建一个简单的 Dockerfile:

nano Dockerfile

将以下内容复制并粘贴到 Dockerfile 中:

FROM ubuntu:22.04

RUN apt-get update && apt-get install -y \
  curl \
  nginx \
  && rm -rf /var/lib/apt/lists/*

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Ctrl+O,然后按 Enter 保存,再按 Ctrl+X 退出 nano。

让我们分解一下这个 Dockerfile:

  • FROM ubuntu:22.04 - 使用 Ubuntu 22.04 作为基础镜像
  • RUN apt-get update... - 更新软件包列表并安装 curl 和 nginx
  • EXPOSE 80 - 指示容器将监听端口 80
  • CMD ["nginx", "-g", "daemon off;"] - 在容器启动时以前台模式运行 nginx

创建一个 .dockerignore 文件

.dockerignore 文件有助于排除构建上下文中不需要的文件和目录,从而使构建更快、更高效:

nano .dockerignore

添加以下内容:

.git
.gitignore
*.md

Ctrl+O,然后按 Enter 保存,再按 Ctrl+X 退出 nano。

验证项目结构

让我们检查一下我们的文件是否已正确创建:

ls -la

你应该看到类似如下的输出:

total 16
drwxrwxr-x 2 labex labex 4096 Jan 1 00:00 .
drwxr-xr-x 3 labex labex 4096 Jan 1 00:00 ..
-rw-rw-r-- 1 labex labex   21 Jan 1 00:00 .dockerignore
-rw-rw-r-- 1 labex labex  159 Jan 1 00:00 Dockerfile

现在我们有了一个基本的 Dockerfile,我们准备好测试 Docker Buildx 并在下一步中探索 "requires exactly 1 argument" 错误。

理解并解决 "Requires Exactly 1 Argument" 错误

在这一步中,我们将故意触发 "requires exactly 1 argument" 错误,以了解其原因,然后学习如何解决它。

触发错误

首先,如果我们还没有进入项目目录,让我们导航到它:

cd ~/project/buildx-test

现在,让我们尝试使用 Docker Buildx 构建镜像,但没有指定构建上下文:

docker buildx build

你应该看到类似如下的错误消息:

"docker buildx build" requires exactly 1 argument.
See 'docker buildx build --help'.

Usage:  docker buildx build [OPTIONS] PATH | URL | -

此错误发生的原因是 docker buildx build 命令需要一个构建上下文(包含 Dockerfile 的目录)作为参数。

理解错误

"requires exactly 1 argument" 错误意味着 Docker Buildx 需要知道在哪里找到构建镜像所需的文件。此参数通常是包含你的 Dockerfile 的目录的路径(构建上下文)。

触发此错误的常见情况包括:

  1. 忘记指定构建上下文
  2. 使用不正确的命令语法
  3. 将选项放置在错误的顺序

纠正错误

让我们通过添加构建上下文来修复该命令。最简单的方法是使用 . 来指示当前目录:

docker buildx build .

这次,Docker 将启动构建过程,但我们会注意到它没有标记镜像,这使得以后很难引用它。

如果构建仍在运行,让我们使用 Ctrl+C 停止构建,然后使用正确的标签重试:

docker buildx build -t nginx-test:latest .

你应该看到显示构建进度的输出:

[+] Building 12.8s (7/7) FINISHED
 => [internal] load build definition from Dockerfile                          0.0s
 => => transferring dockerfile: 203B                                          0.0s
 => [internal] load .dockerignore                                             0.0s
 => => transferring context: 34B                                              0.0s
 => [internal] load metadata for docker.io/library/ubuntu:22.04               0.5s
 => [1/3] FROM docker.io/library/ubuntu:22.04@sha256:...                      0.0s
 => CACHED [2/3] RUN apt-get update && apt-get install -y     curl     nginx  0.0s
 => CACHED [3/3] EXPOSE 80                                                    0.0s
 => exporting to image                                                        0.0s
 => => exporting layers                                                       0.0s
 => => writing image sha256:...                                               0.0s
 => => naming to docker.io/library/nginx-test:latest                          0.0s

使用不同的 Buildx 选项

让我们使用 Docker Buildx 探索一些额外的选项:

  1. 构建并将镜像加载到 Docker 的本地镜像存储中:
docker buildx build --load -t nginx-test:local .
  1. 在不使用构建缓存的情况下构建(强制全新构建):
docker buildx build --no-cache -t nginx-test:nocache .
  1. 构建并仅输出最终的镜像 ID:
docker buildx build -q -t nginx-test:quiet .

验证已构建的镜像

让我们检查一下我们构建的镜像:

docker images | grep nginx-test

你应该看到类似如下的输出:

nginx-test     quiet      abcdef123456   5 minutes ago   123MB
nginx-test     nocache    fedcba654321   5 minutes ago   123MB
nginx-test     local      123456abcdef   5 minutes ago   123MB
nginx-test     latest     abcdef123456   5 minutes ago   123MB

现在你了解了 Docker Buildx 中常见的 "requires exactly 1 argument" 错误,并且知道如何使用各种选项正确构建镜像。

使用 Docker Buildx 构建多架构镜像

Docker Buildx 最强大的功能之一是它能够同时为多个架构构建镜像。在这一步中,我们将学习如何创建多架构镜像。

理解多架构镜像

多架构镜像允许使用相同的镜像名称在不同的平台(如 AMD64、ARM64 等)上运行。当拉取镜像时,Docker 会自动为宿主架构选择合适的版本。

这尤其适用于:

  • 支持基于 x86 和 ARM 的设备
  • 确保你的应用程序在各种云提供商上运行
  • 为具有不同架构的物联网设备构建

设置多架构构建

Docker Buildx 需要配置为进行多架构构建。首先,让我们确保我们的构建器支持此功能:

docker buildx inspect --bootstrap mybuilder

如果你看到关于构建器不可用的错误,让我们使用正确的配置重新创建它:

docker buildx rm mybuilder
docker buildx create --name mybuilder --driver docker-container --bootstrap --use

创建多架构镜像

现在,让我们为多个架构构建我们的 Nginx 镜像:

docker buildx build --platform linux/amd64,linux/arm64 -t nginx-test:multi .

你可能会看到类似如下的错误消息:

error: multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")

发生这种情况是因为默认的 Docker 驱动程序不支持多架构构建。让我们修改我们的方法。

为了演示目的,我们将分别为特定平台构建:

docker buildx build --platform linux/amd64 -t nginx-test:amd64 --load .

这会专门为 AMD64 架构构建镜像,并将其加载到 Docker 的本地镜像存储中。

使用构建参数

Docker Buildx 允许我们使用构建参数来定制我们的构建。让我们修改我们的 Dockerfile 以使用构建参数:

nano Dockerfile

将 Dockerfile 内容更新为:

FROM ubuntu:22.04

ARG PACKAGE=nginx
RUN apt-get update && apt-get install -y \
  curl \
  ${PACKAGE} \
  && rm -rf /var/lib/apt/lists/*

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

Ctrl+O,然后按 Enter 保存,再按 Ctrl+X 退出 nano。

现在我们可以使用自定义软件包构建镜像:

docker buildx build --build-arg PACKAGE=nginx-extras -t nginx-extras:latest .

推送到注册表(可选)

要充分利用多架构镜像,你通常会将它们推送到注册表。这需要 Docker Hub 凭据或私有注册表。在真实世界中,该命令将如下所示:

## 仅供参考 - 本实验不需要
## docker buildx build --platform linux/amd64,linux/arm64 -t username/nginx-test:multi --push .

检查镜像

让我们检查一下我们创建的镜像:

docker images | grep nginx

你应该看到类似如下的输出:

nginx-extras    latest     abcdef123456   1 minute ago    130MB
nginx-test      amd64      123456abcdef   2 minutes ago   123MB
nginx-test      latest     fedcba654321   10 minutes ago  123MB

测试我们的镜像

最后,让我们使用我们的镜像运行一个容器来验证它是否有效:

docker run -d --name test-nginx -p 8080:80 nginx-test:latest

检查容器是否正在运行:

docker ps

你应该看到输出,表明你的容器正在运行:

CONTAINER ID   IMAGE              COMMAND                  CREATED          STATUS          PORTS                  NAMES
abcdef123456   nginx-test:latest  "nginx -g 'daemon of…"   10 seconds ago   Up 10 seconds   0.0.0.0:8080->80/tcp   test-nginx

让我们使用 curl 命令访问 nginx 服务器,以确保它正在响应:

curl http://localhost:8080

你应该看到默认的 Nginx 欢迎页面 HTML。

完成后,清理容器:

docker stop test-nginx
docker rm test-nginx

恭喜你!你已经成功地使用了 Docker Buildx,理解并解决了 "requires exactly 1 argument" 错误,并且学习了如何为不同的架构创建专门的构建。

总结

在这个实验中,你获得了 Docker Buildx 的实践经验,并学习了如何解决常见的 "requires exactly 1 argument" 错误。以下是你完成的任务:

  1. 设置 Docker Buildx 并创建了一个构建器实例
  2. 创建了一个用于测试的基本 Dockerfile
  3. 遇到了、理解了并解决了 "requires exactly 1 argument" 错误
  4. 使用各种选项和配置构建了 Docker 镜像
  5. 学习了多架构镜像构建的基础知识

这些技能为在现代开发环境中与 Docker 合作奠定了坚实的基础,在这些环境中,应用程序通常需要在不同的硬件平台上运行。你现在可以自信地使用 Docker Buildx 来创建高效的、特定于平台的容器镜像,同时避免常见错误。

在你继续 Docker 之旅时,可以考虑探索更高级的 Buildx 功能,将其集成到 CI/CD 管道中,并使用它来构建真正可移植的应用程序,这些应用程序可以在任何地方运行。