1. docker build
1.1. 描述
docker build
命令使用 Dockerfile 和 “上下文” (context) 一起 构建一个新的镜像。镜像构建过程中的“上下文”是指位于指定路径或 URL 中的一组文件,构建过程可以引用“上下文”中任意的文件。例如,在构建过程中可以使用 COPY
指令复制“上下文”中的文件到新镜像中。
URL 参数可以引用三种类型的资源:Git 仓库、预打包的压缩文件和纯文本文件。
Git 仓库作为上下文
当 URL 参数指向 Git 仓库的位置时,该仓库充当构建上下文。系统会递归地获取 Git 仓库及其子模块 , Git 的 commit 提交历史将不会被保存。Git 仓库首先被拉到本地主机上的临时目录中,成功之后,该目录将作为上下文发送给 Docker 守护进程。在拉取仓库时,如果是私有仓库,需要有对应的权限。
注意:
如果 URL 参数包含包含多个子模块,系统将使用
git clone ——recursive
命令递归地克隆存储库及其子模块。
Git URL 在拥有子模块的仓库配置上下文时,用冒号(:)分隔。第一部分表示 Git 将进行 git checkout
的目标,可以是 分支、tag 或远程引用。第二部分表示仓库中的一个子目录,它将用作构建上下文。
例如:运行这个命令在 container 分支中使用一个名为 docker 的目录作为上下文:
$ docker build https://github.com/docker/rootfs.git#container:docker
下表表示了所有有效的后缀及其构建上下文:
Build Syntax Suffix | Commit Used | Build Context Used |
---|---|---|
myrepo.git | refs/heads/master | / |
myrepo.git#mytag | refs/tags/mytag | / |
myrepo.git#mybranch | refs/heads/mybranch | / |
myrepo.git#pull/42/head | refs/pull/42/head | / |
myrepo.git#:myfolder | refs/heads/master | /myfolder |
myrepo.git#master:myfolder | refs/heads/master | /myfolder |
myrepo.git#mytag:myfolder | refs/tags/mytag | /myfolder |
myrepo.git#mybranch:myfolder | refs/heads/mybranch | /myfolder |
注意:
当使用 BuildKit 作为构建器 (DOCKER_BUILDKIT=1) 时,不能指定构建上下文目录(上面示例中的 myfolder)。对该特性的支持可以在
buildkit#1684
中找到。
TAR包作为上下文
如果你传递的 URL 是一个 TAR 包, Docker 客户端不会直接发送一个 TAR 包文件,而是将 URL 本身发送到 Docker 守护进程,由 Docker 守护进程来负责下载解压后作为上下文。
$ docker build http://server/context.tar.gz
下载操作将在 Docker 守护进程运行的主机上执行,该主机不一定与发出构建命令的主机相同。Docker 守护进程将获取 context.tar.gz 并使用它作为构建上下文。
注意:
压缩文件上下文必须是符合标准 UNIX 格式的 tar 归档文件,并且可以用
xz
、bzip2
、gzip
或identity (不压缩)
格式进行解压缩。
纯文本作为上下文
可以不用单独指定上下文,在 URL 中传递单个 Dockerfile 文件,或者通过 STDIN 管道将文件导入。
通过管道导入一个 Dockerfile :
$ docker build - < Dockerfile
在 Windows 的 PowerShell 中,可以运行:
> Get-Content Dockerfile | docker build -
如果使用 STDIN 或指定指向纯文本文件的 URL,系统会将内容放入名为 Dockerfile 的文件中,并且忽略 -f, --file
选项。在这个场景中,没有上下文。
默认情况下,docker 构建命令将在构建上下文的根目录中查找 Dockerfile。-f, --file
选项可以用来指定替代文件的路径。在多次构建使用同一组文件的情况下非常有用。该路径必须是到构建上下文中的文件。如果指定了相对路径,则将其解释为相对于上下文的根。
在大多数情况下,最好将每个 Dockerfile 放在一个空目录中。然后,只将构建 Dockerfile 所需的文件添加到该目录中。为了提高构建的性能,您可以通过向该目录添加 .dockerignore
文件来排除文件和目录。有关创建 dockerignore 的信息,请参见 .dockerignore文件。
如果 Docker 客户端失去了与守护进程的连接,build 构建过程就会被取消。如果你用 CTRL-c
中断 Docker 客户端,或者 Docker 客户端因为任何原因被杀死,就会发生这种情况。如果构建初始化的拉取操作在构建被取消时仍在运行,那么该拉取操作也将被取消。
1.2. 帮助
$ docker build --help
Usage: docker build [OPTIONS] PATH | URL | -
Build an image from a Dockerfile
Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
--build-arg list Set build-time variables
--cache-from strings Images to consider as cache sources
--cgroup-parent string Optional parent cgroup for the container
--compress Compress the build context using gzip
--console Show console output (with buildkit only) (true, false, auto) (default auto)
--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period
--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota
-c, --cpu-shares int CPU shares (relative weight)
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
--disable-content-trust Skip image verification (default true)
-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')
--force-rm Always remove intermediate containers
--iidfile string Write the image ID to the file
--isolation string Container isolation technology
--label list Set metadata for an image
-m, --memory bytes Memory limit
--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap
--network string Set the networking mode for the RUN instructions during build (default "default")
--no-cache Do not use cache when building the image
--platform string Set platform if server is multi-platform capable
--pull Always attempt to pull a newer version of the image
-q, --quiet Suppress the build output and print image ID on success
--rm Remove intermediate containers after a successful build (default true)
--security-opt strings Security options
--shm-size bytes Size of /dev/shm
--squash Squash newly built layers into a single new layer
--stream Stream attaches to server to negotiate build context
-t, --tag list Name and optionally a tag in the 'name:tag' format
--target string Set the target build stage to build.
--ulimit ulimit Ulimit options (default [])
1.3. 选项
名字,简写 | 默认值 | 描述 |
---|---|---|
--add-host | - | 添加自定义的主机到IP映射(主机:IP) |
--build-arg | - | 设置构建时变量,一般和 Dockerfile 中的 ARG 配合使用 |
--cache-from | - | 要考虑作为缓存源的 image |
--cgroup-parent | - | 容器的可选父 cgroup |
--compress | false | 使用 gzip 压缩构建上下文 |
--console | auto | 只在 buildkit 下使用,显示终端输出 (true, false, auto) |
--cpu-period | 0 | 限制 CPU CFS(完全公平调度程序)期限 |
--cpu-quota | 0 | 限制 CPU CFS(完全公平调度程序)配额 |
--cpu-shares,-c | 0 | CPU 份额(相对重量) |
--cpuset-cpu | - | 允许执行的 CPU(如:0-3,0,1) |
--cpuset-mems | - | 允许执行的 MEM(如:0-3,0,1) |
--disable-content-trust | true | 跳过 image 验证 |
--file,-f | - | Dockerfile 的完整路径(默认为当前目录下 Dockerfile 文件) |
--force-rm | false | 始终删除中间容器 |
--iidfile | - | 将图像 ID 写入文件 |
--isolation | default | 容器隔离技术,默认 --isolation="default",即 Linux 命名空间;其他还有 process 或 hyperv |
--label | - | 设置 image 的元数据,和 Dockerfile 中的 LABEL 功能一致 |
--memory, -m | 0 | 内存限制 |
--memory-swap | 0 | 交换限制等于内存加交换:'-1'以启用无限交换 |
--network | - | 在构建期间为 RUN 指令设置联网模式 |
--no-cache | false | 构建 image 时不要使用缓存 |
--platform | - | string Set platform if server is multi-platform capable |
--pull | false | 始终尝试拉取镜像的较新版本 |
--quiet,-q | false | 取消构建输出并在成功时打印图像ID |
--rm | true | Remove intermediate containers after a successful build |
--security-opt | - | 安全选项 |
--shm-size | 0 | /dev/shm 的大小 |
--squash | false | 将新建的图层压缩到单个新图层中 |
--stream | - | Stream attaches to server to negotiate build context |
--tag, -t | - | 以'名称:标记'格式命名和可选的标记 |
--target | - | 设置要构建的目标构建阶段。 |
--ulimit | - | Ulimit 选项 |
1.4. 示例
1.4.1. 使用相对路径进行构建
$ docker build .
Uploading context 10240 bytes
Step 1/3 : FROM busybox
Pulling repository busybox
---> e9aa60c60128MB/2.284 MB (100%) endpoint: https://cdn-registry-1.docker.io/v1/
Step 2/3 : RUN ls -lh /
---> Running in 9c9e81692ae9
total 24
drwxr-xr-x 2 root root 4.0K Mar 12 2013 bin
drwxr-xr-x 5 root root 4.0K Oct 19 00:19 dev
drwxr-xr-x 2 root root 4.0K Oct 19 00:19 etc
drwxr-xr-x 2 root root 4.0K Nov 15 23:34 lib
lrwxrwxrwx 1 root root 3 Mar 12 2013 lib64 -> lib
dr-xr-xr-x 116 root root 0 Nov 15 23:34 proc
lrwxrwxrwx 1 root root 3 Mar 12 2013 sbin -> bin
dr-xr-xr-x 13 root root 0 Nov 15 23:34 sys
drwxr-xr-x 2 root root 4.0K Mar 12 2013 tmp
drwxr-xr-x 2 root root 4.0K Nov 15 23:34 usr
---> b35f4035db3f
Step 3/3 : CMD echo Hello world
---> Running in 02071fceb21b
---> f52f38b7823e
Successfully built f52f38b7823e
Removing intermediate container 9c9e81692ae9
Removing intermediate container 02071fceb21b
本例中指定的路径是当前路径 .
,所以本地目录中所有的文件都会被 tar打包并发送到 Docker 守护进程。路径指定是指在 Docker 守护进程中找到构建的“上下文”文件的位置。请记住,Docker 守护进程可以在远程机器上运行,并且在客户端(在这里运行 docker build)不会发生对 Dockerfile 的解析。这意味着 PATH 中的所有文件都将被发送,而不仅仅是要添加到 Dockerfile 中的文件。
1.4.2. 使用 URL 构建
$ docker build github.com/creack/docker-firefox
这将克隆 GitHub 仓库,并使用克隆的仓库作为上下文。将仓库的根目录中的 Dockerfile 用作构建时的 Dockerfile。可以使用 Git://
或 git@
模式指定任意的Git仓库。
$ docker build -f ctx/Dockerfile http://server/ctx.tar.gz
Downloading context: http://server/ctx.tar.gz [===================>] 240 B/240 B
Step 1/3 : FROM busybox
---> 8c2e06607696
Step 2/3 : ADD ctx/container.cfg /
---> e7829950cee3
Removing intermediate container b35224abf821
Step 3/3 : CMD /bin/ls
---> Running in fbc63d321d73
---> 3286931702ad
Removing intermediate container fbc63d321d73
Successfully built 377c409b35e4
这会将URL http://server/ctx.tar.gz
发送到Docker守护进程,该守护进程下载并提取引用的压缩文件。-f ctx/Dockerfile
参数指定了ctx.tar.gz 中用于构建映像的 Dockerfile 的路径。任何添加命令 Dockerfile 指本地路径必须相对于里面的内容c tx.tar.gz 的根源。在上面的示例中,tarball 包含一个目录 ctx/,所以 ADD ctx/container.cfg /
操作按预期工作。
1.4.3. 使用标准输入 - 构建
$ docker build - < Dockerfile
从标准输入 STDIN 读取一个 Dockerfile ,这种方式构建镜像是没有“上下文”的。由于缺少“上下文”,任何本地目录的内容都不会被发送到 Docker 守护进程,如果要添加文件,只有在 Dockerfile 中引用远程 URL 时才能工作。
$ docker build - < context.tar.gz
这将为从 STDIN 读取的压缩上下文构建一个映像。支持的格式有: bzip2、gzip和xz。
1.4.4. 使用 .dockerignore 文件
$ docker build .
Uploading context 18.829 MB
Uploading context
Step 1/2 : FROM busybox
---> 769b9341d937
Step 2/2 : CMD echo Hello world
---> Using cache
---> 99cc1ad10469
Successfully built 99cc1ad10469
$ echo ".git" > .dockerignore
$ docker build .
Uploading context 6.76 MB
Uploading context
Step 1/2 : FROM busybox
---> 769b9341d937
Step 2/2 : CMD echo Hello world
---> Using cache
---> 99cc1ad10469
Successfully built 99cc1ad10469
这个例子展示了如何使用 .dockerignore
文件从上下文中排除 .git
目录。它的效果可以从上传上下文的大小变化中看到。生成器引用包含关于创建 .dockerignore
文件的详细信息。
当使用 BuildKit 后端时,docker build
会搜索相对于 Dockerfile 名称的 .dockerignore
文件。例如,运行 docker build -f myapp.Dockerfile .
首先寻找一个名为 myapp.Dockerfile.dockerignore
的忽略文件。如果没有找到这样的文件,则使用 .dockerignore
文件(如果存在)。如果一个项目包含多个 Dockerfile,这些 Dockerfile 可能会忽略不同的文件集,那么使用基于 .dockerignore
的 Dockerfile 非常有用。
1.4.5. 构建时指定镜像tag -t
$ docker build -t vieux/apache:2.0 .
这将像上一个示例一样构建,但是它将标记生成的 image 镜像。存储库名称将为 vieux/apache
,标签将为2.0
。阅读有关有标签的更多信息。
可以对 image 镜像配置多个标记。例如,您可以将最新的标记应用于新构建的镜像,并添加引用特定版本的另一个标记。例如,要将一个镜像同时标记为 whenry/fedora-jboss:latest
和 whenry/fedora-jboss:v2.1
,使用以下方法:
$ docker build -t whenry/fedora-jboss:latest -t whenry/fedora-jboss:v2.1 .
1.4.6. 构建时指定 Dockerfile -f
$ docker build -f Dockerfile.debug .
这将使用一个名为 Dockerfile.debug
的文件作为构建指令,而不是 Dockerfile
。
$ curl example.com/remote/Dockerfile | docker build -f - .
上面的命令将使用当前目录作为构建上下文,并从stdin中读取Dockerfile。
$ docker build -f dockerfiles/Dockerfile.debug -t myapp_debug .
$ docker build -f dockerfiles/Dockerfile.prod -t myapp_prod .
上面的命令将构建两次当前构建上下文(由 .
指定),一次使用 Dockerfile 的调试版本,一次使用生产版本。
$ cd /home/me/myapp/some/dir/really/deep
$ docker build -f /home/me/myapp/dockerfiles/debug /home/me/myapp
$ docker build -f ../../../../dockerfiles/debug /home/me/myapp
这两个 docker 构建命令执行完全相同的操作。它们都使用调试文件的内容,而不是寻找 Dockerfile,并使用 /home/me/myapp
作为构建上下文的根。请注意,debug 位于构建上下文的目录结构中,而与您在命令行中如何引用它无关。
注意:
如果文件或目录在上传的上下文中不存在,
docker build
会返回一个no such file or directory
错误。如果没有上下文,或者指定的文件位于主机系统的其他位置,可能会发生这种情况。出于安全原因,上下文仅限于当前目录(及其子目录),并确保可在远程 Docker 主机上进行可重复构建。这也是ADD ../file
不工作的原因。
1.4.7. 其他参数
其他参数使用频率较低,详见