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 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允许执行的MEM(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上,唯一支持的选项是default选项,它使用Linux命名空间。在Microsoft Windows上,您可以指定以下值

描述
default使用Docker守护进程的--exec-opt指定的值。如果守护进程未指定隔离技术,则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指令)时,压缩步骤将失败(参见问题 #33823)。

前提条件

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

您可以使用--experimental标志启动 Docker 守护程序或在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>,并且存在一个带有注释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