容器里 rm 一个来自镜像的文件,下层的文件明明还在,怎么就“消失”了?这篇直接读 upperdir:whiteout 是什么类型的文件,删除后重建目录为什么带一个 opaque 属性,以及 docker commit 后它们在镜像层里变成什么。
初始 upperdir:(空) rm /gone.txt 之后 upperdir:gone.txt upperdir/gone.txt 是:character special file, 主设备号:次设备号 = 0:0 容器里 ls /gone.txt:ls: /gone.txt: No such file or directory upperdir/gone.txt 的大小:0 字节
下层(镜像层)是只读的,删除只能在可写层里“标记”。upperdir 里出现一个同名的字符设备,主设备号 0、次设备号 0,大小 0 字节;合并视图因此不再显示这个文件。
upperdir/tmp 里:(空)(创建又删除一个只在可写层的文件)
删除只存在于可写层的文件,upperdir 里不留痕迹:下层没有这个名字,就没什么需要遮住。
rm -rf /dir 之后 upperdir/dir 是:character special file, 主设备号:次设备号 = 0:0;容器里 ls /dir:ls: /dir: No such file or directory
重新 mkdir /dir 并写入 c.txt 之后 upperdir/dir 是:directory, 主设备号:次设备号 = 0:0;里面有:c.txt
upperdir/dir 的扩展属性:{'trusted.overlay.opaque': 'y'}
容器里 ls /dir:c.txt(原来的 a.txt、b.txt 被这个 opaque 目录整个盖住了)rm -rf 一个目录,在 upperdir 里是同名的 0:0 字符设备。之后再 mkdir 同名目录,它是普通目录,但带 trusted.overlay.opaque=y 扩展属性,下层同名目录里的文件(a.txt、b.txt)不再透出。我是用特权容器挂载 upperdir 后用 Python 读到的这个属性。
upperdir/keep.txt 是:regular file, 主设备号:次设备号 = 0:0;内容:again
文件删除后又用同名创建,upperdir 里只是一个普通文件,不需要 whiteout。
commit 退出码 0;镜像共 3 层,最后一层(只含这个容器的改动)的条目:['dir', 'dir/.wh.a.txt', 'dir/.wh.b.txt', 'dir/c.txt', '.wh.gone.txt', 'keep.txt']
运行时的 whiteout 和镜像层里的 whiteout 是两种形式:docker commit 后,新层 tar 里是 .wh.gone.txt、dir/.wh.a.txt 这样的条目。这次 commit 里目录没有出现 .wh..wh..opq,而是逐个文件写了 .wh.——别的构建方式(Dockerfile 里的 RUN rm)产生什么,见 c3。