理解 docker 镜像底层原理, 对于开发 docker 镜像和阅读 dockerfile 具有一定的指导作用
什么是镜像
简单理解为软件包, 可以使用 docker 服务执行的一种软件包, 是一种轻量级, 用于打包软件本身与软件运行环境的一种软件包, 镜像需要再容器中启动, 启动后的预期与结果总是一致, 并不会受到操作系统, 软硬件的差异影响, 所以镜像是跨平台的, 利于部署的, 这完全依托于镜像的构成理念, 与 docker 对于此的底层支持
UnionFS 与镜像之间的关系
UnionFS 是一种文件系统, 由 linux 操作系统提供, Linux各发行版实现的UnionFS各不相同, 所以Docker在不同linux发行版中使用的也不同
可以通过docker info来查看docker使用的是哪种, 如:
- centos, docker18.03.1-ce: Storage Driver: overlay2
- debain, docker17.03.2-ce: Storage Driver: aufs
UnionFS 可以通过
1
$ mount -t aufs -o dirs=./x1:./x2 none ./xxx
把 x1 和 x2 挂载至 xxx 上, 这样在 xxx 上就可以看到两个文件夹的内容了
默认情况下, 最左边的文件夹(x1)是读写的, 其余全是只读, 除非显示声明 mount -t aufs -o dirs=./x1=rw:./x2=rw none ./xxx
如果尝试修改 x2 里的文件, 则会在 x1 下创建一个同名的被修改过后内容的文件, 并不会动 x2 的文件(因为是是只读)
如果是删除 x1 和 x2 的文件, 则 x1 里的文件会真删, x2 里的文件则会在 x1 内创建一个 .wh.文件名 的文件, 来标注文件被排除忽略显示, 删除一个文件和在 x1 里添加一个 wh 文件是一样的效果
查看一个容器的挂载信息
1
2
3
4
5
6
$ ls /var/lib/docker/image/unionfs类型/layerdb/mounts/容器ID
$ cat mount-id
#查看所有挂载点
$ cat /proc/mounts
bootfs rootfs
bootfs(boot file system) 主要包含bootloader 和 kernel,bootloader 主要用于引导加载 kernel,当 kernel 被加载到内存中后 bootfs 会被 umount 掉。
rootfs (root file system) 包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc 等标准目录和文件
不同的 linux 发行版(如 ubuntu 和 CentOS ) 在 rootfs 这一层会有所区别,体现发行版本的差异性。
传统的 Linux 加载 bootfs 时会先将 rootfs 设为 read-only,然后在系统自检之后将 rootfs 从 read-only 改为 read-write, 然后我们就可以在 rootfs 上进行读写操作了。但 Docker 在 bootfs 自检完毕之后并不会把 rootfs 的 read-only 改为 read-write, 而是利用 union mount(UnionFS 的一种挂载机制)将 image 中的其他的 layer 加载到之前的 read-only 的 rootfs层之上, 每一层 layer 都是 rootfs 的结构,并且是read-only 的。所以,我们是无法修改一个已有镜像里面的 layer 的!只有当我们创建一个容器, 也就是将 Docker 镜像进行实例化,系统会分配一层空的 read-write 的 rootfs ,用于保存我们做的修改。一层 layer 所保存的修改是增量式的, 就像 git 一样。
综上,image其实就是一个文件系统(rootfs),它与宿主机的内核一起为程序提供一个虚拟的linux环境。在启动docker container时,依据image,docker会为container构建出一个虚拟的linux环境。
对于一个精简的os,rootfs可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用host的kernal,自己只需要提供rootfs就可以了。 由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
总结
- 镜像是 rootfs 的打包产物
- linux 不同的发行版, bootfs 基本一致
- docker 容器是一个运行在宿主机内核的一个进程, 进程运行结束, 容器也就停止了
- 镜像的分层实际是利用的 unionfs 分层技术, 所以 layer 是只读的, layer 的概念也可以减少重复资源的生成
- rootfs 是系统启动需要挂在的第一个文件系统, 其内包含了 linux 运行标准目录和shell命令, 用来制备 linux 运行环境