Docker如何构建缓存以及何时不使用它
1. 简介
Docker 构建过程可能需要一些时间才能完成。它可能会下载基础镜像、复制文件以及下载和安装软件包,仅提及一些常见任务。这就是docker build 使用缓存 的原因。
在本教程中,我们将详细了解构建过程以及何时最好避免使用缓存。
2. 关于Docker Build Cache
Docker 镜像 是分层构建的 ,其中每一层都是来自Dockerfile的指令。层相互堆叠,逐步添加功能。
现在让我们看一个简单的Dockerfile来说明构建过程是如何工作的:
FROM alpine:latest
RUN apk add --no-cache bash
ADD entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
上面的 Docker 镜像运行一个脚本entrypoint.sh,它每分钟打印一次当前日期和时间并休眠 60 秒:
#!/bin/bash
while :
do
echo $(date)
sleep 60
done
当我们第一次构建镜像时,所有四个步骤都会执行,但是下次我们构建时,过程会发生变化:
$ docker build -t print-date-time .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM alpine:3.12
---> a24bb4013296
Step 2/4 : RUN apk add --no-cache bash
---> Using cache
---> 52f7aaec5411
Step 3/4 : ADD entrypoint.sh /
---> Using cache
---> 66ba9eee7c3c
Step 4/4 : ENTRYPOINT ["/entrypoint.sh"]
---> Using cache
---> 91a39deabc0b
Successfully built 91a39deabc0b
Successfully tagged print-date-time:latest
构建过程知道Dockerfile没有改变,所以它使用了最后一次构建的缓存来处理所有四个层。如果一条线发生了变化,它将从该线开始重建图层。
Docker 构建过程还检查使用ADD或COPY指令添加的文件中的更改。在我们的示例中,如果我们更改了entrypoint.sh脚本,则将重建第 3 步和第 4 步的层。
这种优化可以让我们在创建图像时节省时间,因为我们可能会多次构建和运行它。但有时缓存会阻止图像更新。
3. 什么时候不使用缓存
Dockerfile可能包含下载和安装工具的说明。在前面的示例中,我们安装了bash。虽然不需要执行脚本,但该行用于说明问题。
假设 Bash 包在 Alpine Linux 上进行了更新以修复安全问题。我们的Dockerfile不会捕捉到变化,因此不会重建镜像。
在克隆 Git 存储库时尤其如此。git clone命令可能永远不会改变,但 repo 会。
避免这些问题的最简单解决方案是根本不使用缓存:
$ docker build -t print-date-time --no-cache .
no-cache参数将完全丢弃缓存,始终执行Dockerfile的所有步骤。
FROM指令是唯一不受no-cache参数影响的行。**如果机器中存在基础映像,则不会再次拉取它。**我们可以通过尝试再次拉取图像来强制执行新的拉取:
$ docker build -t print-date-time --pull .
pull参数在我们的示例中很有用,因为最新标签必然会经常更改。
请注意,虽然这些工具对本地开发很有帮助,但我们要小心提取最新的生产环境。在这些情况下,使用特定标签比只选择最新标签更安全。 这样,我们就可以避免因意外更改破坏映像而带来的令人不快的惊喜。