Docker学习笔记十二:镜像构建时的缓存机制

时间:2024-05-21 21:39:47

在构建映像的过程中,Docker将按照指定的顺序逐步执行您的Dockerfile中的指令。随着每条指令的检查,Docker将在其缓存中查找可重用的现有映像,而不是创建一个新的(重复)映像。如果您不想使用缓存,可以在docker build命令中使用--no-cache = true选项。但是,如果您确实让Docker使用其缓存,那么了解何时会找到匹配的映像是非常重要的。
Docker将遵循的基本规则如下:

  1. 从已经在缓存中的父镜像开始,将下一个指令与从该基本镜像导出的所有子镜像进行比较,以查看其中一个是否使用完全相同的指令构建。如果没有,则缓存无效;
  2. 在大多数情况下,只需将Dockerfile中的指令与其中一个子镜像进行比较即可(通过比较是否与上一次执行的指令一致)。但是,某些指令需要一些额外的检查。对于ADD和COPY指令,将检查镜像中文件的内容,并为每个文件计算校验和。在这些校验和中不考虑文件的最后修改和最后访问的时间。在缓存查找期间,将校验和与现有映像中的校验和进行比较。如果文件(如内容和元数据)中有任何变化,则缓存无效;
  3. 除了ADD和COPY命令之外,缓存检查将不会查看容器中的文件来确定缓存匹配。例如,当处理RUN apt-get -y update命令时,不会检查在容器中更新的文件以确定是否存在高速缓存命中,它将只会检查命令字符串是否与之前的一致来判断是否匹配。

一旦某一层的缓存无效,所有后续的Dockerfile命令将生成新的镜像,并且高速缓存将不被使用。

我想现在你应该已经明白了Dockerfile构建过程的缓存机制了,希望这些知识能够帮助你今后更好地使用Dockerfile。
Docker官方对缓存的介绍

实例

我想使用Dockerfile构建一个基于centos并拥有Java运行环境的镜像,我的Dockerfile如下所示:
Docker学习笔记十二:镜像构建时的缓存机制
然后我使用docker build -t javaimage:v1.0 .这条命令去构建该镜像。经过长时间的下载,等待之后,镜像终于构建好了,但是我突然发现,我的JAVA_HOME环境变量竟然有问题,我竟然将jre1.8.0_144写成了jre1.8.0_14。于是我重新修改了Dockerfile文件,然后docker build -t javaimage:v1.0 .进行构建。

Docker学习笔记十二:镜像构建时的缓存机制
令人惊喜的是,这一次构建过程一下子就完成了。好像它根本不需要重新下载jre一样,那究竟是怎么回事呢?下面是第二次执行docker build -t javaimage:v1.0 .的情况。可以发现,在执行RUN指令时,显示了Using cache,也就是使用了缓存的意思。就是它让我们跳过了漫长的等待过程!
Docker学习笔记十二:镜像构建时的缓存机制