语法
RUN --mount=[type=<TYPE>][,option=<value>[,option=<value>]...]
这里--mount挂载的类型一共有五种:
bind(default) | 用于挂载一个上下文目录 |
cache | 主要用于挂载一个临时目录来缓存编译器和包管理器的目录。 |
tmpfs | 主要用于挂载一个tmpfs |
secret | 允许构建容器访问诸如私钥之类的安全文件,并且此类文件不会出现在构建好的镜像中,避免密钥外泄。 |
ssh | 允许构建容器通过SSH代理访问SSH密钥,并支持密码短语 |
本篇介绍第二种挂载方式 --mount=type=cache
在官方文档中,对cache类型挂载的释义是 "挂载一个临时目录来缓存编译器和包管理器的目录" 。但这里不一定只是编译器或者包管理器,可以是任意的缓存目录。这里有四个需要注意的点:
- 由于RUN指令是容器构建阶段生效运行,所以缓存目录也仅仅在构建阶段可以访问。
- 由于不同的RUN指令会创建新的层,所以只有同一个RUN指令中,才可以访问挂在过来的缓存目录。
- 缓存目录可能会被Docker的GC清理
- cache类型的挂载方式是为了提高构建效率,但是如果多个镜像进行构建的时候,需要大量覆盖缓存中的文件,那么使用这种方式并不明智。这种缓存主要用于多次构建都没有重大修改的情况
可选参数
id | 缓存唯一标志,用于做缓存隔离。比如不同版本使用不同ID。就可以实现访问不同版本下构建所需的缓存了。 |
target | 挂载路径 |
ro,readonly | 指定挂载目录是否只读 |
sharing | 值:shared、private、locked。shared表示缓存可以被并发写入,private表示如果有多个写入者的情况下,创建一个新的挂载,locked表示串行写入(不允许并发写入) |
from | 指定基础的缓存挂载镜像,默认是空目录 |
source | from指定的基础镜像的子路径 |
mode | 设置缓存目录的权限,默认755 |
uid | 设置缓存目录的用户ID。默认是0 |
gid | 设置组ID。默认是0 |
举个栗子:
为了演示更加清楚,这里我将/var/my/cache指定为我的缓存目录。实际应用中,我们将多个镜像构建过程中产生的相同缓存目录进行挂载。比如将apt安装时的缓存目录进行挂载
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt update && apt-get --no-install-recommends install -y gcc
- 先创建一个基础镜像cache-base:v1.0.0,并在/var/my/cache下新建一个info.cache文档。这里模拟的首次构建时向缓存目录中写入文件。
dockerfile:
FROM alpine
RUN --mount=type=cache,target=/var/my/cache/,sharing=locked \
echo 'this is cache text' >> /var/my/cache/info.text
- 再创建另一个镜像cache-ref:v1.0.0,这个镜像试着读取缓存中的文件,验证新的构建是否可以共用上次构建的缓存,并对该文件进行修改
dockerfile:
FROM alpine
RUN --mount=type=cache,target=/var/my/cache/,sharing=locked \
cp /var/my/cache/info.text / ; \ #将缓存中的文件拷贝到根目录
echo 'add new text ' >> /var/my/cache/info.text #修改缓存中的文件
- 创建第三个镜像cache-end:v1.0.0,这个镜像去读取缓存中的文件,验证缓存是否被修改
dockerfile:
FROM alpine
RUN --mount=type=cache,target=/var/my/cache/,sharing=locked \
cp /var/my/cache/info.text / #拷贝缓存中的文件
镜像构建
我们先构建第一个镜像:
然后构建第二个镜像:
用第二个镜像启动容器,可以看到,我们将挂载到缓存中的文件拷贝到镜像中了。
然后构建第三个镜像
因为在构建第二个镜像的时候,往info.text中添加了新行。这时候我们会看见从缓存中复制到镜像的文件,也是修改后的文件