aufs是一种支持联合挂载的文件系统,将不同目录挂载到同一个目录下面,只有最上层是可读可写,下层都是只读层。
docker镜像是由一个或多个aufs branch组成,并且所有branch均为只读权限。
运行容器的时候,创建一个aufs branch位于image层之上,具有rw权限,并把所有branch挂载到一个mnt目录下。
修改/etc/docker/daemon.json,选择使用aufs,然后重启docker
{
"storage-driver": "aufs"
}
查看刚开始目录如下
diff是实际数据来源,layers为每层依赖的层描述文件,mnt是挂载点
看下其他文件
/var/lib/docker/image/aufs/repositories.json记录了镜像的元数据
{"Repositories":{"registry":{"registry:latest":"sha256:b2b03e9146e1c7197e63f67d0d48b87b2b18a6e40660f9d89e6d0b450b6bfa38","registry@sha256:51bb55f23ef7e25ac9b8313b139a8dd45baa832943c8ad8f7da2ddad6355b3c8":"sha256:b2b03e9146e1c7197e63f67d0d48b87b2b18a6e40660f9d89e6d0b450b6bfa38"}}}
先创建一个容器
docker run -d -p 5000:5000 -v /etc/docker/registry/:/var/lib/registry --restart=always --name registry registry
8ccaadc69fe999150fd476ba31d70f4331bb9b8a3feef6306720998a1a2ea981
在/var/lib/docker/image/aufs/layerdb/mounts/容器id/mount-id文件里可以找到mount id
比如mountid为a6c4f5...
/var/lib/docker/aufs/mnt/下就会看到a6c4f5...和a6c4f5...-init目录
/var/lib/docker/aufs/layers/a6c4f5...记录这层依赖的层的cache-id
/var/lib/docker/aufs/diff/a6c4f5...-init用于处理系统环境配置和用户配置自动生成的内容,如dns配置
所以docker容器的文件系统有3层,可读写层,init层,只读层
当docker commit把容器提交成镜像后,diff下会生成一个cacheid文件夹,容器本身的mountid文件夹会被删除
网上找了几张图
如上图中基于同一个Image运行两个容器,低层Image一致,每启动一个新容器,便会新建一个目录作为aufs branch并与Image branch进行联合挂载。
容器文件读写删除
当容器需要修改一个文件,而该文件位于低层branch时,顶层branch会直接复制低层branch的文件至顶层再进行修改,而低层的文件不变,这种方式即是CoW技术(写复制),AUFS默认支持Cow技术。
当容器删除一个低层branch文件时,只是在顶层branch对该文件进行重命名并隐藏,实际并未删除文件,只是不可见,这种方式即AUFS的whiteout(写隐藏)。