很多人以为 docker build 会把整个目录打包发给守护进程。BuildKit 其实只传 Dockerfile 里用到的文件,而且是增量的。这篇用一个带 50 MiB 无关文件的目录实测:到底传了多少、第二次传了多少、改一个文件传了多少,以及上下文之外的东西为什么够不着。
[只 COPY app.txt] 退出码 0 用时 564 ms
#1 transferring dockerfile: 76B done
#3 transferring context: 2B done
#4 [internal] load build context
#4 transferring context: 40B done
[COPY . /ctx/] 退出码 0 用时 1923 ms
#1 transferring dockerfile: 67B done
#3 transferring context: 2B done
#5 [internal] load build context
#5 transferring context: 52.44MB 0.5s doneBuildKit 的 [internal] load build context 一步,在 Dockerfile 只 COPY app.txt 时只传了 40 B,尽管目录里有 50 MiB 的随机文件;改成 COPY . 才传 52.44 MB。所以“上下文很大导致构建慢”主要发生在 COPY . 这类写法上。
[COPY . /ctx/ 第 2 次] 退出码 0,用时 304 ms
#1 transferring dockerfile: 67B done
#3 transferring context: 2B done
#4 [internal] load build context
#4 transferring context: 137B done
#6 CACHED再构建一次,上下文传输只有 137 B(我推测只是比对了文件元数据,没有验证),COPY 层 CACHED,304 ms;改了 app.txt 后传输 155 B,50 MiB 的大文件没重传。但 COPY . /ctx/ 这一层因为目录内容变了仍要重做,1450 ms。
[COPY . /ctx/ 改了 app.txt] 退出码 0,用时 1450 ms
#1 transferring dockerfile: 67B done
#3 transferring context: 2B done
#4 [internal] load build context
#4 transferring context: 155B done用 docker build - 从标准输入读 Dockerfile 没有上下文,COPY 找不到文件;COPY ../secret.txt 也出不了上下文,报的是 “not found”。用 -f 可以把 Dockerfile 放在别处,上下文由最后一个目录参数决定。
退出码 1;#6 ERROR: failed to calculate checksum of ref <id>: "/app.txt": not found | ERROR: failed to build: failed to solve: failed to compute cache key: failed to calculate checksum of ref <id>: "/app.txt": not found
压缩传输、远程上下文(git URL)、.dockerignore 的影响(下一篇)和旧的非 BuildKit 构建器都没有在本文实验。
退出码 1;#6 ERROR: failed to calculate checksum of ref <id>: "/secret.txt": not found | ERROR: failed to build: failed to solve: failed to compute cache key: failed to calculate checksum of ref <id>: "/secret.txt": not found
--progress plain 输出里,transferring context: N 前面的编号对应哪一步,#3 是读取 .dockerignore,[internal] load build context 才是真正传文件的那一步。
退出码 0,用时 209 ms;#1 transferring dockerfile: 97B done
上下文的成本是“Dockerfile 用到的文件”的成本,而不是“目录有多大”。真正要避免的是 COPY . . 这种把一切都纳入的写法,以及这一层随便一个文件变化都要重建的后果。