容器

容器(container)就是一个特殊的进程:
1.从全局来看,新建了一个容器只是增加了一条进程,有自己的PID号
2.从容器里看,他自己的PID号是1

实现上述说法,用到了Linux的Cgroups与Namespace
1.Cgroups用于控制一个进程(容器)可以使用的资源(比如只能用20%CPU)
2.Namespace用于控制一个进程(容器)可以看到/交互的别的进程/磁盘/网络

这两者相辅相成的限制将一个普通的进程变成了特殊的进程——容器。

综上,一个正在运行的Docker容器,其实就是一个启用了多个Linux Namespace的应用进程,而这个继承能够使用的资源量,则受Cgroups配置的限制。

由于一个容器的本质就是一个进程,用户的应用进程实际上就是容器里PID=1的进程,也是其他后续创建的所有进程的父进程。这就意味着,在一个容器中,你没办法同时运行两个不同的应用,除非你能事先找到一个公共的PID=1的程序来充当两个不同应用的父进程。

文件系统

对于每一个容器来说,他们虽然共享Linux内核,但是文件系统却只是宿主机上的某个文件夹。

通过pivot_root或chroot改变容器内“/”目录的视野,让容器把指定文件夹当做根节点。

镜像

对于每一个镜像而言,他们都是通过增量的形式把一整个操作系统所必须的文件,联合挂载在该根目录下。

一共有三层:

只读层(ro+wh)

一般是完整的操作系统文件(rw)

Init层(ro+wh)

容器对只读层“操作系统”的更改,比如更改容器的hostname。
我们只想要更改容器的hostname而非宿主机的hostname,同时也希望它只对当前容器有效,不希望执行docker commit时,把这些信息连同可读写层一起提交。

可读写层(ro)

用户自定义的应用,文件等

ro:readOnly,只读
wh:whiteOut,对于只读层,如果你想要删除一些文件,那么操作就会以增量的形式记录下来,对于该容器,它“遮罩”了只读层被删除的文件,但是没有真正删除掉只读层的文件。称之为白障
cw: Copy-on-Write,读写层通常称为容器层,只读层称为镜像层,所有的CRUD操作都只会作用于容器层,相同的文件上层会覆盖地掉下层,所以修改一个文件时,会从上到下查找有没有这个文件,找到之,就复制到容器层中,修改,修改的结果会作用到下层文件,称为Copy-on-Write。

最终把三个层打包起来(Init层不会提交,它记录的是对可读层系统文件的修改),就可以实现,既不修改可读层,还可以有最大自由的“在容器里随意操作整个操作系统的文件”。

而,可以把“操作系统”打包起来,完美复现镜像制作者当初的完整环境,就是容器技术的“强一致性”的重要体现。

docker exec原理

前面我们知道docker容器在Linux下就是一个进程,当我们执行docker exec进入容器时候,实际是新建了一个新的进程,然后加入到了docker容器的Linux Namespace下,此时我们所在的“新的进程”,就可以共享到docker容器的Linux Namespace下的所有内容。也就实现了“进入”一个容器。

docker只能有一个 一个docker容器里有几个进程_docker