Docker镜像的联合文件系统(Union File System)是Docker使用的一种文件系统技术。它允许将多个文件系统层(File System Layers)以一种有效的方式组合在一起,形成一个单一的可读写的文件系统。
联合文件系统采用分层的结构,其中每个文件系统层都是一个只读的文件系统。每个层都包含一个或多个文件或目录的快照。当容器运行时,这些层按照定义的顺序叠加在一起,形成一个容器的文件系统视图。
1. 基础镜像层(Base Image Layer):这是 Docker 镜像的初始层,通常包含操作系统的基本文件系统。基础镜像层是只读的,不可更改。
2. 镜像层(Image Layers):在基础镜像层之上,可以有一个或多个镜像层。每个镜像层都包含了一组文件或目录的快照。镜像层是只读的,可以在多个镜像之间共享。
3. 容器层(Container Layer):当使用镜像创建容器时,会在镜像层的顶部添加一个容器层。容器层是可写的,用于存储容器运行时的文件修改和数据。
4. 挂载点(Mount Point):Docker 容器可以将主机上的目录或文件挂载到容器内的指定路径。挂载点允许容器访问主机的文件系统,以实现数据共享和持久化存储。
联合文件系统通过将这些部分以一种有效的方式组合在一起,形成一个单一的可读写的文件系统。容器在运行时会将这些层叠加在一起,形成一个完整的容器文件系统视图。
从上述图中可以看到三个层结构,即lowerdir、upperdir、merged层;对应的,使用docker inspect [容器ID]就可以看到这几个层所在的位置。
"GraphDriver": {
"Name": "overlay2",
"Data": {
"LowerDir": "/var/lib/docker/overlay2/45abab78c6fd022d9ce132a0fb995f9e91bc0a807ccc73e2461fce6c9b68b250/root",
"MergedDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/merged",
"UpperDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/upper",
"WorkDir": "/var/lib/docker/overlay2/dc838cbc7d903a4bfd6bd0280a6910c063f2d1f03439e917ebc773fccc377402/work"
}
}
其中lowerdir是只读的镜像层(image layer),其中就包含bootfs/rootfs层,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,当boot成功 kernel 被加载到内存中,bootfs就被umount了,rootfs(root file system)包含的就是典型Linux系统中的/dev、/proc、/bin、/etc等标准目录。
lowerdir是可以分很多层的,除了bootfs/rootfs层以外,还可以通过Dockerfile建立很多image层,构建过程如下:
Dockerfile中每一个指令都会生成一个新的image层,如上图所示。
当FROM时就已经生成了bootfs/rootfs层,也就是kernel和base层。
upperdir层是lowerdir的上一层,只有这一层可读可写的,其实就是Container层,在启动一个容器的时候会在最后的image层的上一层自动创建,所有对容器数据的更改都会发生在这一层。
merged层就是联合挂载层,也就是给用户暴露的统一视觉,将image层和container层结合,就如最上边的图中描述一致,同一文件,在此层会展示离它最近的层级里的文件内容,或者可以理解为,只要container层中有此文件,便展示container层中的文件内容,若container层中没有,则展示image层中的。
如果文件在upperdir(容器)层,直接读取文件;
如果文件不在upperdir(容器)层,则从镜像层(lowerdir)读取;
首次写入:如果upperdir中不存在,overlay和overlay2执行copy_up操作,把文件从lowdir拷贝到upperdir中,由于overlayfs是文件级别的(即使只有很少的一点修改,也会产生copy_up的动作),后续对同一文件的再次写入操作将对已经复制到容器层的文件副本进行修改,这也就是尝尝说的写时复制(copy-on-write)。
删除文件或目录:当文件被删除时,在容器层(upperdir)创建whiteout文件,镜像层(lowerdir)的文件是不会被删除的,因为它们是只读的,但without文件会阻止它们显示,当目录被删除时,在容器层(upperdir)一个不透明的目录,这个和上边的whiteout的原理一样,组织用户继续访问,image层不会发生改变
copy_up操作只发生在文件首次写入,以后都是只修改副本,
overlayfs只适用两层目录,,相比于比AUFS,查找搜索都更快。
容器层的文件删除只是一个“障眼法”,是靠whiteout文件将其遮挡,image层并没有删除,这也就是为什么使用docker commit 提交保存的镜像会越来越大,无论在容器层怎么删除数据,image层都不会改变。
节省存储空间:由于每个文件系统层都是只读的,并且可以在多个镜像之间共享,所以可以节省存储空间。相同的文件或目录只需要在底层的文件系统层中存储一次。
快速构建和部署:当构建 Docker 镜像时,只需将新的更改添加到现有的文件系统层中,而不需要重新复制整个文件系统。这样可以加快构建和部署的速度。
版本控制和回滚:每个文件系统层都可以看作是一个快照,可以轻松地回滚到先前的版本。这使得管理和维护镜像变得更加简单和可控。
分发和共享:联合文件系统使得镜像的分发和共享变得更加高效。只需传输更改的层,而不需要传输整个镜像。
常用的联合文件系统实现包括 OverlayFS、AUFS、btrfs 等。在不同的操作系统和 Docker 版本中,可能使用不同的联合文件系统实现。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。