Docker项目未待创建的用户进程做了以下事情
- 启用Linux Namespace配置
- 设置指定的Cgroups参数
- 切换进程的跟目录(Change Root)
注意
- rootfs只是一个操作系统所包含的文件,配置和目录,并不包括操作系统内核
- 在Linux操作系统中,这两部分是分开存放的
- 操作系统只有在开机启动时才会加载执行指定版本的内核镜像
- rootfs只包括了操作系统的"躯壳",并没有包括操作系统的"灵魂"
容器操作系统的"灵魂"
- 同一台机器上的所有容器,都共享宿主机操作系统的内核
- 容器内的与内核相关的内核参数,内核模块,和内核的直接交互都是"全局变量",牵一发而动全身
容器的一致性
- 无论在本地,云端,还是在一台任何地方的的机器上
- 用户只需要解压打包好的容器镜像,那么这个应用运行所需要的完整的执行环境就被重现出来了
- 深入到操作系统级别的运行环境一致性,打通了应用在本地开发和远端执行环境之间难以逾越的鸿沟
联合文件系统(UnionFS)
第一层,只读层
他是这个容器的rootf最下面的五层,对应的正是ubuntu:latest镜像的五层
可以看到它们的挂载方式都是只读的(ro+wh即readonly+whiteout)
第二层,可读写层
它是容器rootfs最上面的一层,挂载方式为rw,即read write
在没有写入文件之前,这个目录是空的.而且一旦在容器里面做了写操作,
你的修改就会以增量的方式出现在这个层中
删除文件时,AuFS会在可读写层创建一个whiteout文件,把只读层里的文件遮挡起来
第三部分,init层
它是一个以"-init"结尾的层,夹在只读层和读写层之间
init层是Docker项目单独生成的一个内部层,专门用来存放/etc/hosts, /etc/resolv.conf等信息
需要这样一层的原因是,这些文件本来属于只读层的Ubuntu镜像的一部分
但是用户往往需要在容器启动时就写入一些指定的值比如hostname,所以就需要在读写层对他们进行修改
可以,这些修改往往只对当前的容器有效,我们并不希望执行docker commit时,
把这些信息连同可读写层一起提交掉,所以docker的做法是,在修改了这些文件之后,
以一个单独的层挂载了出来,用户执行docker commit只会提交可读写层,所以是不包含这些内容的
分层镜像的设计好处
- 以Docker镜像为核心,将不同技术人员紧密的联系在了一起
- 容器镜像是增量式的,每次镜像拉取,推送的内容,比完整操作系统要小得多
- 镜像发布之后,在全世界的任何地方下载这个镜像,可以完全复制镜像制作者当时的环境