语法

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 /                             #拷贝缓存中的文件

镜像构建

        我们先构建第一个镜像:

docker 终端挂起 docker run 挂文件_运维

         然后构建第二个镜像:

docker 终端挂起 docker run 挂文件_linux_02

         用第二个镜像启动容器,可以看到,我们将挂载到缓存中的文件拷贝到镜像中了。

docker 终端挂起 docker run 挂文件_linux_03

         然后构建第三个镜像

docker 终端挂起 docker run 挂文件_运维_04

        因为在构建第二个镜像的时候,往info.text中添加了新行。这时候我们会看见从缓存中复制到镜像的文件,也是修改后的文件

docker 终端挂起 docker run 挂文件_容器_05