刚开始学容器时,我最困惑的是:都是"隔离",Docker 凭什么比虚拟机快那么多?
答案就两个字:内核。
架构上的根本差别
【虚拟机】 【容器】
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 应用 A │ │ 应用 B │ │ 应用 A │ │ 应用 B │
├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤
│ 依赖/库 │ │ 依赖/库 │ │ 依赖/库 │ │ 依赖/库 │
├──────────┤ ├──────────┤ └────┬─────┘ └────┬─────┘
│ Guest OS │ │ Guest OS │ │ │
│ (完整!) │ │ (完整!) │ ┌────┴────────────┴────┐
├──────────┴─┴──────────┤ │ Docker Engine │
│ Hypervisor │ ├──────────────────────┤
├───────────────────────┤ │ 宿主机内核(共用) │
│ 宿主机操作系统 │ ├──────────────────────┤
└───────────────────────┘ └──────────────────────┘
每台虚拟机都要跑一个完整系统 容器只是被隔离的普通进程
关键差别:虚拟机里每台都要装一个完整的操作系统(Guest OS),而所有容器共用宿主机的内核。
量化对比
| 维度 | 虚拟机 | 容器 |
|---|---|---|
| 启动时间 | 几十秒 ~ 几分钟 | 毫秒 ~ 秒级 |
| 磁盘占用 | 几 GB 起(含完整系统) | 几十 MB 起(只含应用和依赖) |
| 内存开销 | 每台要分固定内存 | 按进程实际使用 |
| 隔离级别 | 硬件级(Hypervisor) | 进程级(namespace + cgroup) |
| 安全性 | 更强,逃逸难度高 | 共享内核,逃逸风险更高 |
| 能跑不同内核吗 | 能(Windows 跑 Linux) | 不能,必须同内核 |
容器是怎么实现隔离的
Docker 没有发明新技术,它把 Linux 早就有的两个能力组合起来:
| 机制 | 作用 | 类比 |
|---|---|---|
| Namespace | 让进程"看不见"外面的东西 | 把眼睛蒙上 |
| Cgroup | 限制进程能用多少 CPU / 内存 | 把钱包限额 |
# 查看一个容器的 namespace
ls -l /proc/$(docker inspect -f '{{.State.Pid}}' 容器名)/ns/
# 查看 cgroup 限制
cat /sys/fs/cgroup/system.slice/docker-*.scope/memory.max
所以容器里的进程,在宿主机上就是一个普通进程,只是被"蒙了眼、限了额"。
什么场景不该用容器
- 需要跑不同内核:Windows 容器和 Linux 容器不能混在一台机器上共用内核
- 强隔离要求:多租户、跑不可信代码,虚拟机的硬件隔离更稳
- 需要完整系统环境:某些老软件依赖特定内核模块,容器里装不了
- 有状态的重负载数据库:不是不能跑,但存储和网络要额外设计
总结
- 虚拟机虚拟的是硬件,容器虚拟的是操作系统
- 容器快,是因为没有 Guest OS,共用内核
- 隔离靠 namespace(看不见)+ cgroup(用不多)
- 共用内核是优点也是安全边界,不是什么都能塞进容器
理解了这个层次关系,后面学 Kubernetes 才不会觉得是"凭空冒出来的一堆概念"。