Docker相关原理

2019-05-10

Docker相关原理

Linux的namespace机制

namespace(命名空间)是Linux提供的轻量级虚拟化方式,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。命名空间建立系统的不同视图,从用户来看一个视图像一台单独的Linux计算机一样,有自己的init进程;子命名空间的进程映射到父命名空间的进程,所以父命名空间知道每一个子命名空间的运行状态;而每一个子命名空间则是相互隔离的,互相不知道对方存在。

$ sudo docker start 213a008c34bd
$ ps -af | grep docker
root     20460 20417  0 20:23 pts/0    00:00:00 dockerd
root     20971 20460  0 20:25 pts/0    00:00:00 /usr/local/docker/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.2 -container-port 3000

如输出所示,在父命名空间中,运行的Docker容器可以被看见是一个进程,可以查看其信息。而在子命名空间中则无法看见父命名空间和其他兄弟命名空间的状态信息。

Docker 的容器就是使用上述技术实现与宿主机器的进程隔离,当我们每次运行 docker run 或者 docker start 时,都会创建一个用于设置进程间隔离的命名空间,实现了不同的容器间独立运行。

网桥模式

Docker为所有的容器设置独立的IP地址和端口资源,容器之间、主机之间不共享网络端口。当Docker启动时,会创建虚拟网桥docker0,它连容器的虚拟网卡和主机的物理网卡形成一个网络。

当Dockerd启动时可以看见如下输出,即网桥启动成功

INFO[2019-05-10T20:23:24.770258143+08:00] Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address 

当然用命令查询也是可以的:

$ dockerd &
#省略一堆启动输出
$ sudo apt-get install bridge-utils #如果还没有网桥工具就装一个
$ brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242040bf136	no	

当我启动了一个简单的docker服务

$ docker run -p 80:3000 service-demo #一个简单的输出helloworld的http服务
$ sudo iptables -t nat -L

#..省略前面的

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  anywhere             anywhere            
DNAT       tcp  --  anywhere             anywhere             tcp dpt:http to:172.17.0.2:3000

如上所示,我的http端口(80)端口被NAT连接到了IP地址172.17.0.2(Docker给容器分配的虚拟IP地址)的3000端口,完成了让容器暴露出来的某一数据端口为主机服务的功能。

目录隔离

Docker的设计不允许容器修改父命名空间中的文件和目录。为了达成这一点,Docker容器自己拥有根文件系统(rootfs),就像一个虚拟机一样。

实现方法类似使用Linux的chroot命令,给每个容器改变一个root,不允许其访问root上级的文件。可以使用Docker提供的cp进行容器和本机器间文件的传递。

CGroups

CGroups是Linux Control Groups机制的简称,是用来隔离物理资源(如CPU、内存)的机制。2007 年进入 Linux 2.6.24 内核,CGroups 不是全新创造的,它将进程管理从 cpuset 中剥离出来,作者是 Google 的 Paul Menage。CGroups 也是 LXC 为实现虚拟化所使用的资源管理手段。

简单的理解,CGroups就是类似Linux的用户和用户组的关系,进程可以属于某个Group中,加入到某个CGroup中的进程其资源分配受该CGroup的限制,不能去申请其他Group的资源。

启动这个容器时,Docker 会为这个容器创建一个与容器标识符相同的 CGroup,将容器能够使用的资源独立出来互不影响,也解决了多个容器时每个容器的资源占用问题。

参考文章:

https://www.cnblogs.com/SzeCheng/p/6822905.html

https://www.cnblogs.com/gispathfinder/p/5871043.html

https://www.ibm.com/developerworks/cn/linux/1506_cgroup/index.html

https://draveness.me/docker