docker build (传统构建器)

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

描述

重要

本页面指的是 旧版实现docker build, 使用的是旧版(BuildKit 之前)构建后端。 此配置仅与构建 Windows 容器相关。

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

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

使用 docker build 调用的构建默认使用 Buildx(和 BuildKit),除非:

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

本页面的描述仅涵盖旧版构建器独有的信息,以及旧版构建器中的行为与 BuildKit 中的行为存在偏差的情况。有关旧版构建器和 BuildKit 共有的功能和标志(例如 --tag--target)的信息,请参阅 docker buildx build 的文档。

使用传统构建器构建上下文

构建上下文是您在调用 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允许执行操作的 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=<value> 选项用于设置容器的隔离技术。在 Linux 上,唯一支持的是使用 Linux 命名空间的 default 选项。在 Microsoft Windows 上,您可以指定以下值:

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

指定 --isolation 标志而不带值等同于设置 --isolation="default"

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

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

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

概述

注意

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

镜像构建完成后,此标志将新层压缩为一个仅包含单个新层的新镜像。压缩不会破坏任何现有镜像,而是创建一个包含已压缩层内容的新镜像。这有效地使得所有 Dockerfile 命令看起来像是创建于单个层。 --squash 标志保留构建缓存。

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

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

已知限制

--squash 选项有一些已知的限制:

  • 在压缩层时,生成的镜像无法利用与其他镜像的层共享,并且可能会占用更多的空间。仍然支持共享基础镜像。
  • 使用此选项时,由于存储了镜像的两个副本,您可能会看到占用的空间显著增加:一个用于包含所有缓存层的构建缓存,另一个用于压缩后的版本。
  • 虽然压缩层可能会生成较小的镜像,但这可能会对性能产生负面影响,因为提取单个层需要更长的时间,而且无法并行下载单个层。
  • 当尝试压缩一个没有对文件系统进行更改的镜像时(例如,Dockerfile 只包含 ENV 条指令),压缩步骤将会失败(参见 issue #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