如何使用 docker buildx imagetools create 命令合并和标记镜像

DockerDockerBeginner
立即练习

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

简介

在本实验中,你将学习如何高效使用 docker buildx imagetools create 命令来合并和标记 Docker 镜像。通过动手实践,你将掌握如何通过合并多个源镜像的内容来创建新镜像,这是构建复杂应用程序时的常见操作。

接下来,你将探索如何为新创建的镜像打标签,使用 --dry-run 参数在不推送的情况下预览最终镜像结构,并为镜像索引添加有价值的注解(annotations)以实现更好的组织结构和元数据管理。完成本实验后,你将牢固掌握如何运用 docker buildx imagetools create 进行高级镜像操作和管理。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ContainerOperationsGroup(["Container Operations"]) docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ContainerOperationsGroup -.-> docker/inspect("Inspect Container") docker/ContainerOperationsGroup -.-> docker/create("Create Container") docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/ImageOperationsGroup -.-> docker/tag("Tag an Image") docker/ImageOperationsGroup -.-> docker/images("List Images") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/inspect -.-> lab-555057{{"如何使用 docker buildx imagetools create 命令合并和标记镜像"}} docker/create -.-> lab-555057{{"如何使用 docker buildx imagetools create 命令合并和标记镜像"}} docker/pull -.-> lab-555057{{"如何使用 docker buildx imagetools create 命令合并和标记镜像"}} docker/tag -.-> lab-555057{{"如何使用 docker buildx imagetools create 命令合并和标记镜像"}} docker/images -.-> lab-555057{{"如何使用 docker buildx imagetools create 命令合并和标记镜像"}} docker/build -.-> lab-555057{{"如何使用 docker buildx imagetools create 命令合并和标记镜像"}} end

从多个源镜像创建新镜像

在这一步骤中,我们将学习如何通过合并多个源镜像的内容来创建新的 Docker 镜像。当你需要构建包含来自不同基础镜像或预构建镜像组件的镜像时,这是常见场景。

首先,让我们拉取必要的源镜像。我们将以 ubuntualpine 镜像为例。

docker pull ubuntu:latest
docker pull alpine:latest

你将看到镜像正在被拉取的输出信息。

latest: Pulling from library/ubuntu
...
Status: Downloaded newer image for ubuntu:latest
latest: Pulling from library/alpine
...
Status: Downloaded newer image for alpine:latest

现在,我们将使用 Dockerfile 创建新镜像。Dockerfile 是一个文本文件,包含用户可以通过命令行调用的所有命令来组装镜像。在你的 ~/project 目录中创建一个名为 Dockerfile 的新文件。

nano ~/project/Dockerfile

将以下内容添加到 Dockerfile 中:

FROM ubuntu:latest AS base
FROM alpine:latest AS alpine_base

COPY --from=alpine_base /etc/alpine-release /app/alpine-release
COPY --from=base /etc/os-release /app/ubuntu-release

WORKDIR /app

CMD ["ls", "-l"]

让我们分解这个 Dockerfile

  • FROM ubuntu:latest AS base:这行将我们构建的第一阶段基础镜像设置为 ubuntu:latest,并将此阶段命名为 base
  • FROM alpine:latest AS alpine_base:这行开始一个新的构建阶段,使用 alpine:latest 作为基础镜像,并将此阶段命名为 alpine_base。这是一个多阶段构建,允许我们在阶段之间复制文件。
  • COPY --from=alpine_base /etc/alpine-release /app/alpine-release:此命令从 alpine_base 阶段复制文件 /etc/alpine-release 到当前阶段的 /app/alpine-release 目录。
  • COPY --from=base /etc/os-release /app/ubuntu-release:此命令从 base 阶段复制文件 /etc/os-release 到当前阶段的 /app/ubuntu-release 目录。
  • WORKDIR /app:这将后续指令的工作目录设置为 /app
  • CMD ["ls", "-l"]:这指定了从此镜像启动容器时要运行的默认命令。它将列出 /app 目录的内容。

Ctrl + X,然后 YEnter 保存 Dockerfile

现在,使用 docker build 命令构建镜像。命令末尾的 . 指定了构建上下文,即当前目录 (~/project)。

docker build -t my-multi-stage-image:latest ~/project

你将看到构建过程的输出,包括正在执行的不同阶段。

[+] Building
...
Successfully built <image_id>
Successfully tagged my-multi-stage-image:latest

构建完成后,你可以通过列出本地镜像来验证镜像是否创建成功。

docker images my-multi-stage-image

你应该能在列表中看到新创建的镜像。

REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
my-multi-stage-image   latest    <image_id>     About a minute ago   ...MB

最后,让我们从这个镜像运行一个容器来查看复制的文件。

docker run --rm my-multi-stage-image:latest

--rm 标志会在容器退出时自动删除它。输出应显示从 ubuntualpine 镜像复制的文件。

total 8
-rw-r--r-- 1 root root 25 Aug 24 10:00 alpine-release
-rw-r--r-- 1 root root 281 Aug 24 10:00 ubuntu-release

这证实了我们通过使用多阶段构建合并多个源镜像的内容成功创建了一个新镜像。

为新创建的镜像添加标签

在这一步骤中,我们将学习如何为前一步骤创建的 Docker 镜像添加额外标签。为镜像打标签有助于版本控制、区分不同构建版本,或将镜像与特定仓库关联。

在前一步骤中,我们构建了一个镜像并自动标记为 my-multi-stage-image:latest。现在,让我们为这个镜像添加另一个标签,例如 my-multi-stage-image:v1.0

docker tag 命令用于创建一个指向源镜像(SOURCE_IMAGE)的目标标签(TARGET_IMAGE)。其语法为 docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

首先,让我们列出已有镜像以确认 my-multi-stage-image:latest 的镜像 ID。

docker images my-multi-stage-image

你将看到类似以下的输出,其中 <image_id> 是你镜像的唯一标识符:

REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
my-multi-stage-image   latest    <image_id>     ...             ...MB

现在,使用 docker tag 命令为该镜像添加 v1.0 标签。你可以使用镜像名称和标签(my-multi-stage-image:latest)或镜像 ID(<image_id>)作为源。通常使用名称和标签更为简便。

docker tag my-multi-stage-image:latest my-multi-stage-image:v1.0

此命令会创建一个指向 my-multi-stage-image:latest 相同镜像 ID 的新标签 v1.0。如果命令执行成功,将不会有任何输出。

为验证新标签是否添加成功,再次列出镜像。

docker images my-multi-stage-image

现在你应该能看到同一个镜像 ID 关联的两个标签:

REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
my-multi-stage-image   latest    <image_id>     ...             ...MB
my-multi-stage-image   v1.0      <image_id>     ...             ...MB

你已成功为 Docker 镜像添加了新标签。现在你可以通过不同的名称或版本来引用同一个镜像。

使用 --dry-run 预览最终镜像(不实际推送)

在本步骤中,我们将学习如何在不实际执行推送操作的情况下,查看即将推送到镜像仓库的最终镜像详情。这在分享镜像前检查镜像清单(manifest)和配置时非常有用。

docker manifest 命令允许你查看和管理镜像清单。镜像清单是一个 JSON 文档,描述了镜像的组成,包括其层级、配置,以及可能包含的跨平台镜像引用(manifest list)。

要预览 my-multi-stage-image:latest 镜像的清单而不实际推送,我们可以使用带 --dry-run 标志的 docker manifest inspect 命令:

docker manifest inspect --dry-run my-multi-stage-image:latest

该命令会将镜像清单以 JSON 格式输出到终端。--dry-run 标志会阻止命令尝试连接镜像仓库或推送任何数据。

输出结果将是一个描述镜像详细结构的 JSON,包含以下信息:

  • 镜像配置
  • 组成镜像的各个层级(通过摘要值表示)
  • 其他元数据
{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
   "config": {
      "mediaType": "application/vnd.docker.container.image.v1+json",
      "size": ...,
      "digest": "sha256:..."
   },
   "layers": [
      {
         "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
         "size": ...,
         "digest": "sha256:..."
      },
      ...
   ]
}

通过分析这个输出,你可以了解镜像在仓库中的实际存储结构和内容组成。这对于调试或验证镜像构建结果特别有帮助。

注意:JSON 输出的具体内容会根据镜像的层级结构和配置而有所不同。

为创建的镜像索引添加注解

在本步骤中,我们将学习如何为镜像索引(也称为 manifest list)添加注解。镜像索引用于引用多个镜像清单(manifest),通常用于不同架构或操作系统。为索引添加注解可以提供关于整个镜像集的元数据信息。

虽然当前的 my-multi-stage-image 是单架构镜像,但我们仍可以演示为其清单添加注解的概念(在这种情况下清单充当简单索引)。

docker manifest annotate 命令用于为 manifest list 中的特定镜像添加或更新注解。其语法为 docker manifest annotate MANIFEST_LIST IMAGE --annotation KEY=VALUE

首先,让我们为镜像创建 manifest list。由于只有一个镜像,该 manifest list 将仅引用现有镜像。我们使用 docker manifest create 命令:

docker manifest create my-multi-stage-image:annotated my-multi-stage-image:latest

此命令创建名为 my-multi-stage-image:annotated 的新 manifest list,其中包含对 my-multi-stage-image:latest 的引用。成功执行后不会有输出。

现在,我们可以使用 docker manifest annotate 命令为 my-multi-stage-image:annotated manifest list 中的 my-multi-stage-image:latest 条目添加注解。让我们添加一个标识操作系统的注解:

docker manifest annotate my-multi-stage-image:annotated my-multi-stage-image:latest --annotation "os=linux"

此命令为 my-multi-stage-image:annotated list 中的 my-multi-stage-image:latest 条目添加了 os=linux 注解。同样,成功执行后不会有输出。

要验证注解是否添加成功,可以使用 docker manifest inspect 检查 manifest list:

docker manifest inspect my-multi-stage-image:annotated

输出将是表示 manifest list 的 JSON 结构。你可以在 my-multi-stage-image:latest 条目中看到添加的注解,具体位于 "manifests" 数组内的 "annotations" 字段:

{
   "schemaVersion": 2,
   "mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
   "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": ...,
         "digest": "sha256:...",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         },
         "annotations": {
            "os": "linux"
         }
      }
   ]
}

你已成功为镜像索引添加了注解。这些注解提供了有价值的元数据,可帮助镜像仓库和客户端更好地理解所处理的镜像信息。

总结

在本实验中,我们学习了如何使用 docker buildx imagetools create 命令来合并和标记镜像。我们首先通过多阶段 Dockerfile 从多个源镜像创建新镜像,演示了如何在不同基础镜像之间复制文件。

完成镜像创建后,我们探索了如何为新创建的镜像打标签,并使用 --dry-run 标志预览最终镜像而不实际推送。最后,我们学习了如何为创建的镜像索引添加注解,为合并后的镜像提供额外的元数据。