← 全部笔记

Docker · 1 基础概念

容器是什么:和虚拟机的区别

容器是被隔离的进程,与宿主共享内核;虚拟机有自己的内核。

约 15 分钟 · 截至 2026-11-03,Docker Engine 29.x · 含维护者实测记录 · 本页讨论普通 Linux 容器

虚拟机 / 每台多一个客户内核

两台虚拟机,各有自己的客户内核 从下往上为硬件、宿主内核、Hypervisor、两台虚拟机各自的客户内核、应用与依赖。采用有宿主操作系统的示意。 虚拟机 A虚拟机 B 应用 A + 依赖应用 B + 依赖 客户内核 A客户内核 B Hypervisor · 提供虚拟硬件 宿主内核 物理硬件 · CPU / 内存 / 磁盘

容器 / 进程使用同一个宿主内核

两个容器,共享一个 Linux 宿主内核 容器边界内只有应用进程和依赖文件,没有独立客户内核。运行时管理容器,应用的系统调用由宿主内核处理。 容器 A容器 B 应用进程 A应用进程 B + 依赖文件+ 依赖文件 无独立内核无独立内核 容器运行时 · 创建与管理进程 共享的 Linux 宿主内核 物理硬件 · CPU / 内存 / 磁盘
图 1 容器少的是“每个实例自己的客户内核”这一层,宿主内核仍然在工作。

悬停或用 Tab 聚焦:虚拟机的客户内核 / 容器共享的宿主内核。分层表示管理关系;系统调用不需要经过容器运行时转发。

学完后,你能完成这四件事

01 / 先建立模型

容器隔离进程,虚拟机运行另一套内核

内核(kernel)是操作系统里管理 CPU、内存和设备的核心。程序打开文件或发送数据时,会通过系统调用请求内核完成工作。运行中的程序叫进程(process)。

宿主机(host)是承载运行环境的机器。虚拟机(Virtual Machine,VM)里的系统叫客户系统。Hypervisor 是提供虚拟 CPU、内存等硬件的虚拟化层,让客户系统引导自己的内核。

容器运行时(container runtime)负责创建和管理容器进程。容器内可以有自己的程序、库和文件视图,但这些进程仍由宿主内核执行。图 1 的虚线框是隔离边界,不是另一台物理机器。[1]

在同一个 Linux Docker Engine 上运行 Alpine 和 Ubuntu 容器,你预计它们使用谁的内核?

它们共享宿主内核。Alpine、Ubuntu 的名称可以说明容器里的程序和库来自哪个发行版,不能说明容器有自己的内核。发行版是内核与一组工具组成的系统;容器通常只带这里的工具和文件。

“容器就是轻量虚拟机”容易让你误以为里面有一套启动中的操作系统。更准确的说法是:容器是宿主机上被隔离的一个或一组进程。共享内核也意味着共享一部分风险,隔离不是绝对的。

深入一点:隔离怎么做?图里的 Hypervisor 位置总一样吗?

Linux 的 namespace(命名空间)让进程看到各自的进程、网络等视图;cgroups(控制组)用于统计和限制资源。具体机制留到模块 7,资源上限也需要配置。[3]

图 1 选用有宿主操作系统的虚拟化示意,方便对比。还有直接运行在硬件上的 Hypervisor(常称 Type 1);它下面不必再有一层通用宿主操作系统。两种画法中,每台完整虚拟机都有自己的客户内核这一点相同。

02 / 看启动时少做了什么

容器启动应用,不必再引导一个内核

容器可以直接使用已经运行的宿主内核。虚拟机冷启动通常还要准备虚拟硬件、引导客户内核,再启动客户系统里的服务。下面比较的是运行材料已在本机、宿主环境已启动的简化流程。

虚拟机 / 冷启动

  1. 准备虚拟硬件提供虚拟 CPU、内存、磁盘
  2. 引导客户内核初始化客户系统的核心
  3. 启动系统服务准备客户系统的运行环境
  4. 启动应用应用开始执行

容器 / 启动进程

  1. 准备隔离环境设置文件视图与进程边界
  2. 启动应用进程请求现有宿主内核工作
  1. 先看虚拟机:Hypervisor 为客户系统提供虚拟硬件。
  2. 客户内核从磁盘加载并开始运行。
  3. 客户系统启动应用依赖的系统服务。先猜:应用开始运行前,还剩哪一步?
  4. 虚拟机里的应用开始执行。现在把目光移到右边。
  5. 容器只需准备隔离环境。宿主内核早已在运行。先猜:下一步需要引导 Alpine 的内核吗?
  6. 不需要。应用进程开始执行,使用已有的宿主内核;两条完整路径现在都可见。
图 2 容器省去了客户内核引导;框的高度和播放节奏不表示实测时长。

省去内核引导能减少启动工作量,具体时间仍取决于机器和应用。本页比较启动机制,不提供时延基准;虚拟机快照恢复也不同于冷启动。

还要区分“进程已经运行”和“应用已经能接请求”。第一次运行可能先下载镜像(image)——用于创建容器的程序与文件模板。下载、数据库恢复、应用初始化都可能比启动进程更慢;镜像细节留到下一页。[2]

同一个小程序,镜像已在本机。容器通常比完整虚拟机冷启动更快,关键原因是什么?

打开文件和分配内存仍需要内核;被省去的是另一套内核的引导。

应用可能还要加载数据。启动进程和能够提供服务是两个时刻。

容器创建隔离环境后启动进程,使用现有内核。完整虚拟机冷启动需要先引导自己的客户内核;少做这部分工作是速度差异的机制,不是统一的时延保证。

03 / 在你的机器上验证

对比内核版本,先确认谁是宿主

uname -r 会打印当前运行内核的发行版本字符串。先写下预测,再运行两次命令。下面保留维护者提供的终端记录。实测于 2026-11-04,Docker Engine 29.1.3;Linux 内核 7.3.0-1004-oem,x86_64。

条件:你已经安装并启动 Docker,且有运行容器的权限。若尚未安装,先按官方安装说明或Docker Desktop 文档准备环境,再回来验证。

假设 Docker Engine 直接运行在你当前这台 Linux 上:两次输出会相同吗?请说明你比较的是哪一层。

两次内核版本字符串应相同,下面的实测记录也验证了这一点。第一次向本机内核查询;第二次虽然在 Alpine 容器内执行,也向同一个内核查询。它不会打印 Alpine 的发行版版本。

先在 Linux 宿主机,再在容器里查询

uname -r
7.3.0-1004-oem
docker run --rm alpine uname -r
7.3.0-1004-oem

实测结果:两次都打印 7.3.0-1004-oem,容器查询的是同一个宿主内核。内核版本号保留自原始记录,你的机器会不同;应比较两次输出是否相同。首次缺少 Alpine 镜像时还可能先显示拉取进度,比较最后的内核版本行。

逐段读第二条命令:docker run 创建并启动容器;--rm 在命令结束后删除这个容器;alpine 指定使用的镜像;最后的 uname -r 是在容器里运行的命令。镜像会留在本机,--rm 不会删除它。[2]

实验影响与前提

首次运行可能联网下载镜像并占用磁盘;默认网络模式下,Docker 还可能创建容器网络端点和相关防火墙规则。本实验不挂载宿主目录,也不使用 --privileged。命令完成后容器被移除。

若提示找不到 Docker、无法连接或没有权限,请先解决安装、启动或授权问题,这些错误不是内核对比结果。若 Docker 连接远程机器,容器共享的是那台远程机器的内核。

怎么解释:相同版本与共享内核的模型相符,但只凭版本字符串相同,并不能独立证明是同一个内核实例;两台虚拟机也可能装同一版本。这里是结合已知运行环境做验证。

深入一点:macOS / Windows 上的 Docker Desktop 为什么可能不同?

运行 Linux 容器时,Docker Desktop 在 macOS / Windows 上使用 Linux 虚拟机环境。Windows 的 WSL 2 后端也提供 Linux 内核。因此,容器共享的是这个 Linux 环境的内核,而不是 macOS 或 Windows 的内核。Linux 版 Docker Desktop 也使用虚拟机。[4] [5]

在 macOS 终端运行 uname -r 查询的是 macOS 内核;在 PowerShell 中不一定有这个 Linux 命令。在 WSL 终端中查到的是 WSL 环境的内核,仍需确认 Docker 连接的环境。不能一概要求它们与容器输出相同。

你可以在同一终端连续运行两次 docker run --rm alpine uname -r,比较两个新容器的输出。两次都应反映 Docker 所在 Linux 环境的内核。这是供你自行验证的 Desktop 场景,不属于上面的 Linux 实测记录;不适用于切换到 Windows 容器模式的情况。

把本页实验命令补完整,不添加其他选项。

docker run alpine uname

--rm 控制容器退出后的清理;-r 是传给容器内 uname 的参数。两者属于不同命令,位置也不同。

04 / 把模型用于选择

要换内核选虚拟机,要快建副本先考虑容器

先问是否需要独立内核,再问信任边界,最后看部署速度。虚拟机和容器也可以叠用:用虚拟机分开不同租户,在每台虚拟机里用容器部署应用。[1]

需要不同内核

应用 A
Linux 内核
应用 B
另一个客户内核

先选虚拟机。分别引导和管理客户系统。

复制兼容的应用

应用副本 A · 容器
应用副本 B · 容器
共享一个 Linux 内核

先考虑容器。准备好镜像后快速创建进程。

分开不互信的租户

租户 A · 虚拟机 A
客户内核 A
租户 B · 虚拟机 B
客户内核 B

先考虑虚拟机边界。各自内部仍可用容器。

图 3 需要独立内核时,把边界放在虚拟机;共享内核可接受时,容器便于复制应用。

强隔离指尽量缩小不同工作负载互相影响的范围。普通容器共享内核,不能仅凭“放进容器”就认定可以安全运行不可信代码。虚拟机提供不同的隔离边界,也仍要正确配置与维护。[3]

按题目最关键的约束分类。先点场景,再点方案;可用 Tab 和 Enter 操作。

  • 测试两个不同版本的 Linux 内核
  • 可信 Web 服务,内核兼容、镜像已就绪,需要快速扩容
  • 不互信的租户,要求各自拥有客户内核
  • 租户间用虚拟机分开,租户内快速部署多个应用
优先容器
优先虚拟机
虚拟机 + 容器

是否独立引导内核是第一条分界线。内核兼容且信任边界允许共享时,容器适合快速创建副本;租户之间需要独立内核时,先用虚拟机,再考虑内部的容器部署。

05 / 合上页面也能讲出来

记住边界,再解释速度与选择

Linux 宿主已经有 Docker。你需要测试修改后的 Linux 内核,又要为可信 Web 服务快速增加副本,怎么安排?

容器镜像里即使放了内核文件,也不代表运行时会引导它。

Web 服务本身是进程;若内核兼容,容器可以运行它。

测试新内核需要能独立引导它的环境,因此选虚拟机。Web 副本可以使用现有内核,容器省去重复引导客户系统的步骤;扩容后仍要等应用准备就绪。

先遮住图 1,在纸上重画两列分层。再用两句话解释:“容器少了哪一层?为什么不能靠换镜像就换掉正在用的内核?”

参考:虚拟机是硬件 → 宿主内核 → Hypervisor → 客户内核 → 应用;普通 Linux 容器是硬件 → 宿主内核,上面由运行时管理隔离的应用进程。图中管理层的位置不表示应用系统调用经过它。

  • 指出虚拟机各有客户内核,容器没有独立客户内核。
  • 指出镜像提供程序与文件,进程仍使用宿主内核。
  • 能用“不必重新引导客户内核”解释启动差异。

来源与核查范围

核查日期:2026-11-03;范围:Docker Engine 29.x 的普通 Linux 容器。内核实验引用维护者在 Issue #10 提供的 2026-11-04 记录(Docker Engine 29.1.3,Linux 7.3.0-1004-oem,x86_64)。启动分步图为机制示意,不表示实测时延。

  1. Docker Docs · What is a container?:隔离进程、共享内核、容器与虚拟机叠用。
  2. Docker Docs · Running containers 与 docker container run:命令结构、需要时拉取镜像、退出时 --rm 清理。
  3. Docker Docs · Docker Engine security:namespace、cgroups 与隔离的安全边界。
  4. Docker Docs · Why does Docker Desktop for Linux run a VM?:Desktop 跨平台虚拟机模型。
  5. Docker Docs · WSL 2 backend:Windows 上的 Linux 内核与后端边界。