docker 基本原理
docker 原理
docker 如何虚拟了容器
Linux Namespace 和 Cgroups
Linux Namespace 是linux内核的一个功能,可以用来操作隔离系统资源,比如pid ,userId ,network ,进程,网络接口,挂载点等。
在linux中,可以以用户为核心,为一个用户隔离出一个独立的namespace ,这个namespace中 用户拥有root权限,但是对于整个操作系统来说,还是只有用户的权限。
当前linux 实现了6种不同类型的namespace
- Mount Namespace 隔离挂载和挂载点
- UTS Namespace 用来隔离nodename 和 domainname
- IPC Namespace 隔离System V IPC 和 POSIX message quenus
- PID Namespace 用来隔离进行id ,在每个子空间中看起来都是独立的id
- Network Namespace 隔离网络设备
- User Namespace 隔离用户和用户组
对于linux内核提供了操作隔离的函数,docker在运行时会调用到内核函数Api 来创建namespace
namespace 技术只能显示空间的隔离,而为了能够实现空间的大小,避免竞争,就需要用到Cgoups技术.
linux Cgroup 可以对进程和进程创建的子进程的资源限制,控制,和统计的能力,包括了CPU,内存,存储,网络等;
docker会为每个容器在系统内创建cgroup
docker镜像的文件系统
在拉取一个镜像的时候,docker是一层一层的拉取的,每一层都有一个唯一的id 。这个层可能是一个软件包,或一些类库。
而对于镜像中包含的层本地已经有了就不会重复拉取。大大节省了空间。
docker 中的文件系统的实现基于linux 联合文件系统;
Union File System 简称 UFS
linux 中使用的一种类似于branch的方式将文件进行覆盖,最终生成了一个单一的文件。
这些被称为branch 或者叫做层的文件是 read-only 或 write-only 的;
在做写操作的时候并没有写到源文件上,而是写到一个新的文件上的;并没有改变原来的文件;
有点类似于ps 中图层的操作
AUFS (Advanced Multi-layered unification filesytem) 是基于UFS 的基础上进行改进的系统;
overlay 文件系统也是基于UFS的,但是结构更加的简单.
早期的docker 文件系统使用的是 AUFS ,后来使用的是 overlay 文件系统;
文件系统是Docker镜像的基础。镜像可以通过分层来进行继承, 基于基础镜像(没有父镜像), 可以制作各种具体的应用镜像。
特性: 一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
docker 镜像加载原理

bootfs(boot file system) 主要包含bootloader和kernel, bpotloader 主要是引导加载kernel,当我们加载镜像的时候,会通过bootloader加载kernal,Docker镜像最底层是bootfs,当boot加载完成后整个kernal内核都在内存中了,bootfs也就可以卸载,值得注意的是,bootfs是被所有镜像共用的,许多镜像images都是在base image(rootfs)基础上叠加的
rootfs (root file system),在bootfs之 上.包含的就是典型Linux系统中的/dev, /proc, /bin, /etc等标准目录和文件。rootfs就是 各种不同的操作系统发行版,比如Ubuntu, Centos等等 。
启动的时候 首先加载 bootfs(Boot File System)目录。这个目录里面包括 Bootloader和kerenl。Bootloader用来加载启动 kerenl。当kerenl成功加载到内存中后, bootfs就会释放掉, kerenl随之开始加载rootfs。所有bootfs 是可以共用一套的;
网络虚拟化技术
docker 的网络相关的操作需要linux的网络虚拟化的相关技术来实现;
linxu 支持虚拟出网络设备 比如 Veth,Bridge,Tap 等
Linux Veth
veth 总是成对出现的,一端连着网络协议栈,一端彼此相连。经常用于连接不同的namespace;经常用于连接多个虚拟设备;


Linux Bridge
Linux Bridge 相当于一台交换机,namespace 请求到 bridege上,可以通过报文中的mac地址进行转发.

Linux 路由表
路由表是Linux内核的一个模块,通过路由表来决定某个network namespace 中包的流向,定义了会请求到那个网络设备上。
Linux Iptables
iptables 是一个管理包流动和转送的工具。定义了一套链式处理的结构,在网络包的传输过程中使用不同的策略对包进行加工,传送或丢弃。
MASQUERADE 策略
用于转换源地址
将请求包中的源地址转成网络设备的地址。在namespace 请求外部网络 会携带源地址,但是这个源地址是主机内部的一个namespace中的,外部无法识别,需要做个转换。
DNAT 策略
用于转换目标地址,用于将宿主机上的端口和namespace中的地址端口做映射
那么对于docker中的网络来说;
host 网络就是容器的网络和主机共用一个Network namespace,使用宿主机的IP 和端口;
container 指定某些容器使用一个 Network namespace
Bridge 容器使用独立network Namespace,并连接到docker0虚拟网卡(默认模式)。通过docker0网桥以及Iptables nat表配置与宿主机通信;
所有的容器都通过docker0 网卡进行桥接自定义网络 自定义网络后,会新创建一个类似于docker0 的网桥,其他容器可以选择加入连接或断开连接
参考链接: https://cloud.tencent.com/developer/article/1643536
https://blog.csdn.net/meltsnow/article/details/94490994
参考书籍:<<自己动手写docker>>



