「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。
因为容器都是基于镜像创建的,所以了解镜像的原理和内部结构显得尤为重要。
base 镜像
base 镜像即基础镜像,通常基础镜像表示一个简单的 linux 镜像,比如 ubuntu,我们可以在它的基础之上安装我们需要的软件和 APP。但是严格意义的 base 镜像是需要我们从 0 开始制作的(比如 scratch 就是一个除了 metadata 外没有其他东西的空镜像)。从之前的内容我们已经知道 Docker 的 ubuntu 镜像只有 70 多 MB,但是完整的 ubuntu 镜像一般在 2G 以上,Docker 是怎么将 ubuntu 容器镜像做到这么小的呢?这就得从 Docker 镜像的结构入手来看。
镜像的分层结构
典型的 Linux 系统启动需要两个 FS,即 bootfs 和 rootfs,其分别归属内核空间和用户空间,Linux 启动时加载 bootfs,启动完毕后就会将其卸载掉。而 rootfs 则一直存在,其包含了系统运行需要的/dev,/proc,/bin 等文件目录。base 镜像的内核空间直接使用 Host 的,只需要提供自己的 rootfs 即可,而 rootfs 可以根据自己的需要进行精简,这样就实现了 Docker 镜像的轻量化。容器只能使用 Host 的内核,并且无权修改,如果你的应用只能在某个内核版本下运行,则不建议使用容器,使用虚拟机即可。
镜像分层结构图
如上图所示,新镜像是在 base 镜像的基础上安装软件,每执行一次安装操作就会向镜像增加一层,为什么要采用这种方式呢?因为这样可以共享资源,基于这个镜像创建的不同的容器都共享 image 层,每个容器的不同之处就是各自拥有不同的容器层,用来记录镜像变化的部分,这个特性,我们称其为:Copy-on-Write,即只有镜像发生变化的时候才复制一份到容器层。
总结一下:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。