docker原理
容器技术的兴起源于 PaaS 技术的普及
Docker 项目通过“容器镜像”,解决了应用打包这个根本性难题
容器本身没有价值,有价值的是“容器编排”
Cgroups 和 Namespace
Cgroups 技术是用来制造约束的主要手段,而Namespace 技术则是用来修改进程视图的主要方法
Linux Namespace是Linux提供的一种内核级别环境隔离的方法。不知道你是否还记得很早以前的Unix有一个叫chroot的系统调用(通过修改根目录把用户jail到一个特定目录下),chroot提供了一种简单的隔离模式:chroot内部的文件系统无法访问外部的内容。Linux Namespace在此基础上,提供了对UTS、IPC、mount、PID、network、User等的隔离机制。
PID Namespace,而每个 Namespace 里的应用进程,都会认为自己是当前容器里的第 1 号进程,它们既看不到宿主机里真正的进程空间,也看不到其他 PID Namespace 里的具体情况
Mount、UTS、IPC、Network 和 User 这些 Namespace
Mount Namespace,用于让被隔离进程只看到当前 Namespace 里的挂载点信息;
Network Namespace,用于让被隔离进程看到当前 Namespace 里的网络设备和配置;
UTS Namespace 允许容器有自己的主机名和域名。这意味着你可以为每个容器设置独特的主机名,而不会影响主机或其他容器。
User Namespace 允许容器内的进程以不同的用户ID运行,即使这些ID在主机上不存在或已被其他容器使用。这增加了安全性,因为容器内的进程无法访问主机或其他容器的用户凭据。
IPC全称 Inter-Process Communication,是Unix/Linux下进程间通信的一种方式,IPC有共享内存、信号量、消息队列等方法。所以,为了隔离,我们也需要把IPC给隔离开来,这样,只有在同一个Namespace下的进程才能相互通信。如果你熟悉IPC的原理的话,你会知道,IPC需要有一个全局的ID,即然是全局的,那么就意味着我们的Namespace需要对这个ID隔离,不能让别的Namespace的进程看到所以,Docker 容器这个听起来玄而又玄的概念,实际上是在创建容器进程时,指定了这个进程所需要启用的一组 Namespace 参数。这样,容器就只能“看”到当前 Namespace 所限定的资源、文件、设备、状态,或者配置。而对于宿主机以及其他不相关的程序,它就完全看不到了。所以说,容器,其实是一种特殊的进程而已。
Docker 还专门提供了一个参数,可以让你启动一个容器并“加入”到另一个容器的 Network Namespace 里,这个参数就是 -net,比如:
docker run -it --net container:4ddf4638572d busybox ifconfig
而如果我指定–net=host,就意味着这个容器不会为进程启用 Network Namespace。这就意味着,这个容器拆除了 Network Namespace 的“隔离墙”,所以,它会和宿主机上的其他普通进程一样,直接共享宿主机的网络栈。这就为容器直接操作和使用宿主机网络提供了一个渠道。
控制组(cgroup)用于限制、记录和隔离进程组使用的物理资源(如 CPU、内存、磁盘 I/O 和网络带宽)。
虽然 cgroup 本身不是命名空间,但 Docker 使用 cgroup 来限制容器的资源使用。
Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
/sys/fs/cgroup
Union File System 也叫 UnionFS,最主要的功能是将多个不同位置的目录联合挂载(union mount)到同一个目录下
rootfs组成
第一部分,只读层
第二部分,可读写层
第三部分,Init 层
它是一个以“-init”结尾的层,夹在只读层和读写层之间。Init 层是 Docker 项目单独生成的一个内部层,专门用来存放 /etc/hosts、/etc/resolv.conf 等信息