【读书笔记】07 | 白话容器基础(三):深入理解容器镜像

《深入剖析Kubernetes - 07 | 白话容器基础(三):深入理解容器镜像》


mount namespace 对进程施展了障眼法,改变了进程对于挂载点的认知

我们希望每当创建一个新容器,容器进程看到的文件系统都是一个独立的隔离环境,而不是宿主机的文件系统。为了达到这个目录,需要借助linux 上面的chroot 命令,将/ 目录挂载到指定目录下。通常会在该目录下挂载一个完整的OS系统,例如ubuntu16.04 这样一个完整的iso。这就是所谓的容器镜像,即rootfs。


所以docker 项目核心原理可以概括成以下几个步骤:

(1) 启动linux namespace配置

(2) 设置cgroups

(3) 切换/ 目录挂载点 (choot)

上述提到的操作系统,只包含文件、目录和配置,不包括内核。所以有2个场景需要特别注意:

(1) 修改宿主机上内核参数,会影响该宿主机上所有容器进程(全局影响)

(2) 低版本内核上运行需要高版本支撑的进程或其他内核版本进程(内核兼容性)

问题:是否每次构建镜像,都需要重复构建rootfs?

答案是否定的。通常镜像会分3层,自下而上分别是操作系统OS层、组件层(jdk、nginx等)、应用层(二进制、静态文件、代码层)。

在构建镜像的时候,会增量的创建一个新的rootfs 层,这里借助的主要是联合文件系统(union file system)技术。

Union File System 也叫 UnionFS,最主要的功能是将多个不同位置的目录联合挂载(union mount)到同一个目录下。比如,现在有两个目录 A 和 B,它们分别有两个文件:

image.png

然后通过联合挂载,将A B 两个目录联合挂载到C目录下:

image.png


在Ubuntu  16.04 + Docker  CE 18.05 版本下 ,默认使用AuFS 联合文件系统。

对于 AuFS 来说,它最关键的目录结构在 /var/lib/docker 路径下的 diff 目录:

/var/lib/docker/aufs/diff/

PS:这块可以通过docker inspect 命令查看,例如

image.png

上图中5个层就是增量rootfs,每个层都有一部分文件和目录,最终联合挂载到/var/lib/docker/aufs/mnt/ 目录下

image.png

第一部分是只读层

这部分挂载的方式都为ro + wh (readonly + whiteout)

每一层都包含操作系统的一部分文件、目录


第二部分读写层

作为rootfs 最上一层,挂载方式为rw,即read write 可读写

所有的增删改操作都发生在这一层

PS:删除操作的实现:在读写层创建一个whiteout 文件,把只读层中的真实文件遮挡掉

例如删除一个名为foo 的文件,则容器会在读写层创建一个名为".wh.foo" 的文件,将只读层中的"foo"文件遮挡起来。


第三部分init 层

用于存放系统所需的/etc/hosts 、/etc/resolv.conf 文件

通常hosts、resolv.conf 文件中的配置仅对当前的容器有用,执行docker commit 的时候并不需要将这一层的内容commit 上去


猜你喜欢

转载自blog.51cto.com/pmghong/2399328