Docker aufs存储驱动layer、diff、mnt目录的区别
/var/lib/docker/aufs
layer子目录:
镜像、镜像历史列表、容器、容器INIT分别有对应的文件。文件名和diff目录中各文件夹匹配。文件的内容是就是该镜像的祖先镜像列表
1.12前,文件名和镜像id 容器id一致。
1.12后,不一致。
若需要匹配容器、镜像和对应文件,可通过最近修改时间、最大大小来进行匹配。
镜像或容器删除后,对应文件也会删除。
容器会对应一个-init的文件,比较方便查找。
diff子目录:
对应了Docker镜像的各子镜像;以及容器的对应读写层目录 -init目录。每个目录中,包含了子镜像存储的真实文件和目录。
du -sh *查看各文件夹大小。容器对应的init目录。
通过容器(非-init)目录大小,和容器的大小(docker ps -s)进行匹配
ls | xargs ls查看各文件夹的子目录
通过此命令查看容器对应读写层在哪个目录
cd /var/lib/docker/aufs/diff
find . -name u13-xgp1
find . -name u13-xgp1*
确认获取的文件目录名称,加-init后有匹配的目录。
./c7e526b33a1af13532e836f013e7b651100ded478196b73ab03d5053235c830a/home/oracle/.vnc/u13-xgp1:3.pid
./c7e526b33a1af13532e836f013e7b651100ded478196b73ab03d5053235c830a/home/oracle/.vnc/u13-xgp1:3.log
./c7e526b33a1af13532e836f013e7b651100ded478196b73ab03d5053235c830a/oracle/product/db10g/log/u13-xgp1
cd c7e526b33a1af13532e836f013e7b651100ded478196b73ab03d5053235c830a
查看读写层包含哪些文件,确认可删除的文件后,可在容器中进行定期删除。
可看出oracle容器(u13-xgp1)运行中,读写层包含各目录及大小分别为:
5.3M home
5.5G oracle
108K root
40K tmp
28K var
mnt子目录:
mnt目录中,各子目录,对应了Docker镜像的各子镜像及容器。
当使用该镜像创建一个容器后,在该层又会多出容器对应的层,以及该容器的init层。
运行中的容器映射在 /var/lib/docker/aufs/mnt/下,这就是AUFS给容器和它下层layer的一个mount point。如果容器没有运行了,依然还有这个目录,但却是个空目录,因为AUFS只在容器运行时才映射。除此之外,还有一个-init的目录,表示init层。Docker 1.10之上的版本,目录名同样不和容器ID对应。
容器的可写层存储在目录 /var/lib/docker/aufs/diff/,即使容器停止了,容器对应的目录依然存在。只有删除容器时,对应的目录才会删除。
其他较好说明:
镜像存储管理:Docker镜像设计上将镜像元数据和镜像文件的存储完全分开,Docker在管理镜像层元数据时采用的是从上至下repository,image,layer三个层次。因为docker以分层的形式存储镜像,因此repository和image这两类元数据没有物理上的镜像文件与之对应,而layer则存在物理上的镜像文件与之对应。
repository元数据:位置->/var/lib/docker/image/aufs(graph_driver)/repositories.json,存储了所有repository的名字,tag和对应的镜像ID
image元数据:位置->/var/lib/docker/image/aufs/imagedb/content/sha256/镜像ID,各种镜像相关信息
layer元数据: 位置->/var/lib/docker/image/aufs/layerdb/sha256,包括diff_id,parent,size等信息,其中diffid是通过镜像层内容用sha256算法计算得来。layerdb目录下还有一个mount目录,用于存储容器可读写层的相关信息。
镜像实际文件存放:
docker的镜像管理和存储是完全隔离的,以aufs为例,进入/var/lib/docker下有三个文件夹,分别为diff/,layers/,mnt/。其中mnt为aufs的挂载目录,diff为实际的数据来源,包括只读层和可读写层,layers存放层依赖有关的层描述文件。mnt和layers最初都是空目录,文件数据在diff下,但随后创建容器时mnt和layers目录会慢慢更新。
容器创建过程中的层存储变化:容器创建时会随机生成容器读写层的mountID,并保存在image/aufs/layerdb/mounts/容器id/目录下 ->
在mnt和diff目录下创建以该容器层的mountID同名的子文件夹 ->
在layers目录下创建文件来记录该层依赖的其他镜像层 ->
GraphDriver将diff中容器依赖的所有镜像层目录挂载到mnt目录下,并会生成一个对应当前容器的以mountID-init格式命名的文件夹作为容器的最后一个只读层 ->
diff目录下的mountID命名的子目录作为容器的可读写层,也挂载到mnt目录下。
docker容器设计了mountID-init这一层来记录容器启动时根据系统环境和用户配置自动生成的内容,一般情况下,容器commit操作保存的镜像不会包含这一层内容。严格意义上来讲容器的文件系统有三层:可读写层 / init层 / 只读层。
docker ps -a即可看到容器短id,然后根据这个短id去 var/lib/docker/image/aufs/layerdb/mounts/短id.../ 这个路径下可以查看当前容器的init-id mount-id等。容器未启动时,在对应的mnt目录下的mountID文件夹(/var/lib/docker/aufs/mnt/[mountID]/)是空的,容器启动后,可以看到这个文件夹下挂载了对应的系统文件(/bin /home /proc等等)。如果用户在容器中对容器进行一些操作,这些操作都会被记录在这个文件夹中,当容器被停止时,mnt下对应的mountID目录被卸载,但diff下对应的mountID文件夹还存在,但只限于宿主机。因此如果我们用docker commit把容器提交成镜像时其实就是在diff目录下生成一个新的cacheID命名的文件夹存放最新的差异变化,这样一个新的镜像层就产生了,而原来的diff下以mountID为名的文件夹在容器被删除时也会对应的被删除。