很多人以为 Docker 是轻量级虚拟机,但其实它的底层原理完全不同。今天,我们用一组超萌的卡通图解,彻底搞懂 Docker 到底是什么,以及它为什么这么快。出发!
*说明:Linux系统本身的内核供Docker容器调用,Docker镜像、容器中都不包含Linux系统内核
*说明:Docker镜像中包含的基础系统对应常规系统中的用户空间部分,这部分是包含在镜像文件中的,Docker的镜像和容器中不包含的是系统内核*说明:我们用Docker下载镜像文件时,Docker首先会检查目标镜像中的各层HASH值是否在本地已下载,已下载的就复用,提高空间效率;也就是说:Docker判断『层』能否复用的依据是HASH值*说明:镜像文件中的『层』都是只读的,创建容器后会在所有只读层上面加一个空的可写层。容器运行时所有修改都在这里。那么如果文件、数据要写入的目录在只读层里面怎么办?哎,这里就需要用到写时复制技术!写时复制(Copy-on-Write)—— 关键效率点:*补充说明:OverlayFS 在 Docker 里的标准结构(真实底层)
OverlayFS 固定把目录分成 4 个角色:
Lower:下层只读层(镜像的多层)
Upper:上层可写层(容器运行时修改)
Merged:合并后给容器看到的目录
Work:内部临时目录
容器看到的就是 Merged,它不知道自己实际在读多层文件。
核心:PID Namespace + 其他 Namespace
1. PID Namespace(最关键)
- 容器里看到的 PID 从 1 开始,只看见自己内部的进程
2. Mount Namespace
- 容器看不到宿主机目录结构,只能看到镜像里的 rootfs
3. Network Namespace
4. IPC Namespace
- 容器内进程不能和宿主机 / 其他容器 IPC 通信
5. UTS Namespace
6. User Namespace
*文字内容:Docker容器运行时还需要使用Cgroups 做资源限制给 Docker 提供:资源限制与管控能力
限制 CPU 使用量 / 核数
限制内存最大使用量
限制磁盘 I/O、网络带宽
限制进程数
统计资源使用情况
一句话:防止容器把宿主机资源吃光。
docker exec -it 容器名称 /bin/bash
/bin/bash是在容器内运行的命令:
这个 bash 不是宿主机的 /bin/bash,而是容器镜像里的 bash(用户空间文件)
它运行在容器的用户空间内,所有操作(比如 ls、mkdir)都只能看到容器内的目录 / 文件
它的所有系统调用(比如读文件、创建进程),最终还是交给宿主机内核处理
*文字内容:数据卷,就是绕过容器的文件系统隔离,直接把宿主机上的一个目录 / 文件,“挂” 进容器的用户空间里。*文字内容:由于隔离机制,用户只能看到容器内部的文件和目录,宿主机的文件和目录是看不到的*文字内容:这时我们绕过了容器内的隔离机制,在容器内就直接看到宿主机的目录本身!你看到的、读写的全是宿主机真实目录数据卷的意义:持久化
容器删了,可写层会丢
但挂载的宿主机目录还在
所以叫数据持久化
---[面试题总结]---
1、Docker为什么比虚拟机高效?
答:Docker 之所以比虚拟机高效,核心原因在于架构设计完全不同。虚拟机需要模拟完整硬件、运行独立操作系统内核,资源开销大、启动慢。而 Docker 共享宿主机的 Linux 内核,不做硬件虚拟化,只通过 Namespace 实现环境隔离、Cgroups 做资源限制、OverlayFS 实现镜像分层存储。容器本质就是宿主机上被隔离和限制的普通进程,启动快、损耗低、资源利用率高,因此性能远高于虚拟机。
答:Docker 底层基于 Linux 内核的三大核心技术实现:一是 Namespace,实现进程、网络、文件系统、主机名等资源的隔离,让容器看起来像独立环境;二是 Cgroups,负责对容器的 CPU、内存、磁盘 I/O 等资源进行限制和统计,避免资源争抢;三是 UnionFS/OverlayFS 联合文件系统,实现镜像分层、复用和写时复制,让镜像体积小、启动快、存储高效。容器本身不虚拟硬件和内核,而是共享宿主机内核,本质是被隔离和资源限制的普通进程,因此轻量、高效、启动迅速。3、docker exec -it 命令运行的 /bin/bash 命令在宿主机的还是容器内的?答:容器内的,它来源于容器的基础系统,而这个基础系统相当于普通Linux系统的用户空间部分。Docker本身不包含Linux系统内核,Docker容器运行时调用宿主机的内核,这样做对提升性能非常有利答:绕过容器自身的联合文件系统,通过挂载操作,将宿主机的目录或文件直接映射到容器内部,让宿主机与容器共享同一份真实文件数据,实现数据持久化与双向互通。