docker build (旧版构建器)

描述从 Dockerfile 构建镜像
用法docker image build [OPTIONS] PATH | URL | -
别名
docker image build docker build docker builder build

描述

重要

本页指的是 docker build 的**旧版实现**,使用旧版(pre-BuildKit)构建后端。此配置仅在构建 Windows 容器时相关。

有关使用 Buildx 的默认 docker build 的信息,请参阅 docker buildx build

使用旧版构建器构建时,镜像是通过运行一系列 commit 从 Dockerfile 创建的。与使用 BuildKit 相比,此过程效率低下且速度慢,因此除了构建 Windows 容器之外,此构建策略已弃用。它仍然适用于构建 Windows 容器,因为 BuildKit 尚未完全支持 Windows 的所有功能。

除非满足以下条件,否则通过 docker build 调用的构建默认使用 Buildx(和 BuildKit):

  • 您正在 Windows 容器模式下运行 Docker Engine。
  • 您通过设置环境变量 DOCKER_BUILDKIT=0 明确选择不使用 BuildKit。

本页上的描述仅涵盖旧版构建器独有的信息,以及旧版构建器与 BuildKit 行为不同的情况。有关旧版构建器和 BuildKit 之间通用功能和标志(例如 --tag--target)的信息,请参阅 docker buildx build 的文档。

使用旧版构建器构建上下文

构建上下文是您在调用构建命令时传递的位置参数。在以下示例中,上下文是 .,表示当前工作目录。

$ docker build .

使用旧版构建器时,构建上下文会完整地发送到守护程序。使用 BuildKit 时,只传输构建中使用的文件。旧版构建器不会事先计算需要哪些文件。这意味着对于具有大上下文的构建,上下文传输可能需要很长时间,即使您只使用上下文中包含的文件子集。

因此,使用旧版构建器时,仔细考虑您在指定上下文中包含哪些文件尤为重要。使用 .dockerignore 文件可将构建中不需要的文件和目录排除在构建上下文之外,使其不被发送。

访问构建上下文之外的路径

如果您尝试在 Dockerfile 中使用相对路径访问构建上下文之外的文件,旧版构建器将报错。

FROM alpine
COPY ../../some-dir .
$ docker build .
...
Step 2/2 : COPY ../../some-dir .
COPY failed: forbidden path outside the build context: ../../some-dir ()

另一方面,BuildKit 会剥离超出构建上下文的开头相对路径。以上一个示例为例,路径 COPY ../../some-dir . 在 BuildKit 中会评估为 COPY some-dir .

选项

选项默认值描述
--add-host添加自定义主机到 IP 映射 (host:ip)
--build-arg设置构建时变量
--cache-from要考虑作为缓存源的镜像
--cgroup-parent设置构建期间 RUN 指令的父 cgroup
--compress使用 gzip 压缩构建上下文
--cpu-period限制 CPU CFS(完全公平调度器)周期
--cpu-quota限制 CPU CFS(完全公平调度器)配额
-c, --cpu-sharesCPU 共享(相对权重)
--cpuset-cpus允许执行的 CPU (0-3, 0,1)
--cpuset-mems允许执行的内存(0-3,0,1)
--disable-content-trusttrue跳过镜像验证
-f, --fileDockerfile 的名称(默认为 PATH/Dockerfile
--force-rm始终删除中间容器
--iidfile将镜像 ID 写入文件
--isolation容器隔离技术
--label为镜像设置元数据
-m, --memory内存限制
--memory-swap交换限制等于内存加交换:-1 表示启用无限制交换
--networkAPI 1.25+ 在构建期间为 RUN 指令设置网络模式
--no-cache构建镜像时不使用缓存
--platformAPI 1.38+ 如果服务器支持多平台,则设置平台
--pull始终尝试拉取更新版本的镜像
-q, --quiet抑制构建输出并在成功时打印镜像 ID
--rmtrue成功构建后删除中间容器
--security-opt安全选项
--shm-size/dev/shm 的大小
--squashAPI 1.25+ 实验性(守护程序)将新构建的层压缩为单个新层
-t, --tag名称,可选地带一个 name:tag 格式的标签
--target设置要构建的目标构建阶段。
--ulimitUlimit 选项

示例

为容器指定隔离技术 (--isolation)

此选项在 Windows 上运行 Docker 容器时非常有用。--isolation= 选项设置容器的隔离技术。在 Linux 上,唯一支持的是使用 Linux 命名空间的 default 选项。在 Microsoft Windows 上,您可以指定以下值:

描述
default使用 Docker 守护程序的 --exec-opt 指定的值。如果 daemon 未指定隔离技术,Microsoft Windows 将使用 process 作为其默认值。
进程仅命名空间隔离。
hyperv基于 Hyper-V 虚拟机监控程序分区的隔离。

可选安全选项 (--security-opt)

此标志仅在 Windows 上运行的守护程序上受支持,并且仅支持 credentialspec 选项。credentialspec 必须是 file://spec.txtregistry://keyname 格式。

压缩镜像层 (--squash) (实验性)

概述

注意

--squash 选项是一项实验性功能,不应视为稳定。

镜像构建完成后,此标志将新层压缩成一个新镜像,该镜像仅包含一个新层。压缩不会销毁任何现有镜像,而是创建一个包含压缩层内容的新镜像。这实际上使所有 Dockerfile 命令看起来都只创建了一个层。--squash 标志保留了构建缓存。

如果 Dockerfile 生成了多个修改相同文件的层,例如在一个步骤中创建文件而在另一个步骤中删除文件,则压缩层可能很有益。对于其他用例,压缩镜像实际上可能对性能产生负面影响。拉取由多个层组成的镜像时,守护程序可以并行拉取层,并允许在镜像之间共享层(节省空间)。

对于大多数用例,多阶段构建是更好的选择,因为它们可以对构建进行更精细的控制,并且可以利用构建器中未来的优化。有关更多信息,请参阅多阶段构建部分。

已知限制

--squash 选项存在一些已知限制:

  • 压缩层时,生成的镜像无法利用与其他镜像的层共享,并且可能占用更多空间。基础镜像的共享仍然受支持。
  • 使用此选项时,由于存储了两份镜像副本(一份用于构建缓存,所有缓存层完好无损;一份用于压缩版本),您可能会看到使用的空间显著增加。
  • 虽然压缩层可能会生成更小的镜像,但它可能对性能产生负面影响,因为单个层需要更长时间才能解压缩,并且无法并行下载单个层。
  • 当尝试压缩一个不对文件系统进行更改的镜像(例如,Dockerfile 只包含 ENV 指令)时,压缩步骤将失败(请参阅 问题 #33823)。

先决条件

本页面上的示例使用了 Docker 23.03 中的实验模式。

您可以通过在启动 Docker 守护程序时使用 --experimental 标志,或在 daemon.json 配置文件中设置 experimental: true 来启用实验模式。

默认情况下,实验模式是禁用的。要查看 Docker 守护程序的当前配置,请使用 docker version 命令并检查 Engine 部分中的 Experimental 行。

Client: Docker Engine - Community
 Version:           23.0.3
 API version:       1.42
 Go version:        go1.19.7
 Git commit:        3e7cbfd
 Built:             Tue Apr  4 22:05:41 2023
 OS/Arch:           darwin/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          23.0.3
  API version:      1.42 (minimum version 1.12)
  Go version:       go1.19.7
  Git commit:       59118bf
  Built:            Tue Apr  4 22:05:41 2023
  OS/Arch:          linux/amd64
  Experimental:     true
 [...]

使用 --squash 标志构建镜像

以下是使用 --squash 标志构建的示例。下面是 Dockerfile

FROM busybox
RUN echo hello > /hello
RUN echo world >> /hello
RUN touch remove_me /remove_me
ENV HELLO=world
RUN rm /remove_me

接下来,使用 --squash 标志构建名为 test 的镜像。

$ docker build --squash -t test .

构建完成后,历史记录如下所示。历史记录可能显示某层的名称为 <missing>,并有一个 COMMENT 为 merge 的新层。

$ docker history test

IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
4e10cb5b4cac        3 seconds ago                                                       12 B                merge sha256:88a7b0112a41826885df0e7072698006ee8f621c6ab99fca7fe9151d7b599702 to sha256:47bcc53f74dc94b1920f0b34f6036096526296767650f223433fe65c35f149eb
<missing>           5 minutes ago       /bin/sh -c rm /remove_me                        0 B
<missing>           5 minutes ago       /bin/sh -c #(nop) ENV HELLO=world               0 B
<missing>           5 minutes ago       /bin/sh -c touch remove_me /remove_me           0 B
<missing>           5 minutes ago       /bin/sh -c echo world >> /hello                 0 B
<missing>           6 minutes ago       /bin/sh -c echo hello > /hello                  0 B
<missing>           7 weeks ago         /bin/sh -c #(nop) CMD ["sh"]                    0 B
<missing>           7 weeks ago         /bin/sh -c #(nop) ADD file:47ca6e777c36a4cfff   1.113 MB

测试镜像,检查 /remove_me 是否已删除,确保 hello\nworld/hello 中,确保 HELLO 环境变量的值为 world

© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.