Docker 入门之概念理解
序
为了面向就业或者读研的方向,最近决定开始学习 Docker、Kubernetes 等容器与容器编排技术。这篇文章先总结一下和 Docker 相关的概念辨析,如 Docker 和 VM,Docker 的原理,在 Windows 和 Linux 下运行 Docker 的异同等等。
为什么需要 Docker
受到郝斌老师教学 C 语言的授课方式影响,在学习 Docker 之前,也需要先问一问,为什么需要使用 Docker。
就我个人的使用体会来说,我在以下这些场合遇到或者使用过 Docker:
- 数据库课程中,与 OceanBase DB 交互是通过 Docker 进行的,省去了配置环境的烦心事;
- 在 Github 上执行 Actions 时,需要用到 Docker 来创建一个干净的 runner 来完成任务;
- 软件工程课程中,我们的乙方采用了 Docker 构建前端、后端和数据库应用并交付给我们。
从上述用例中总结一下,Docker 为我们解决了配置环境的难题。如果需要使用某个应用或服务,但手头没有相应的支撑环境;或者需要确保开发、测试、生产环境的一致性——那就用 Docker 的容器来确保环境配置的易用性和一致性吧。
为什么虚拟机不够好
面试的时候经常会被问到,虚拟机和容器的区别,为什么容器能够减少开销。这要从系统结构的角度来认识。
计算机系统的层次结构

先来一张教材中最经典的层次结构图。一个应用软件(如微信、Docker)等运行在第 6 级虚拟机上,也就是应用语言机器。高层的机器需要底层的机器支撑起来,因此,一个程序想跑起来,需要使用某种语言、需要编译器、汇编语言、操作系统的支持,以及最底层的硬件设备。
虚拟机的原理
虚拟机的原理注定了它在配置环境上的不足。虚拟机基于虚拟化技术,使用 Hypervisor 完成对底层硬件的虚拟化任务。这样,环境所依赖的操作系统就可以使用某些虚拟的 CPU、内存等资源。

Hypervisor 有两类,具体的解释,我引用 aws 的说明:
第 1 类虚拟机监控器
第 1 类虚拟机监控器或裸机虚拟机监控器直接与底层计算机硬件交互。裸机虚拟机监控器直接安装在主机的物理硬件上,而不是通过操作系统安装。某些情况下,在计算机的固件中嵌入第 1 类虚拟机监控器。
第 1 类虚拟机监控器直接与服务器硬件协商,为虚拟机分配专用资源。此类虚拟机监控器还可以根据各种虚拟机请求灵活共享资源。
第 2 类虚拟机监控器
第 2 类虚拟机监控器或托管虚拟机管理监控器通过主机的操作系统与底层主机硬件进行交互。第 2 类虚拟机监控器安装在计算机上,在其中作为应用程序运行。
第 2 类虚拟机监控器与操作系统协商以获取底层系统资源。但是,主机操作系统优先为自己的功能和应用程序分配资源,而不是为虚拟工作负载分配资源。
所以第一类 Hypervisor 可以直接和硬件交互,而第二类的只能在 Host OS 上运行,通过宿主机的 OS 与底层硬件交互,速度较慢。第一类的代表是 Hyper-V,第二类的代表是 VMware Workstation 和 VirtualBox。
虚拟机的不足
不管是哪类 Hypervisor,区别只在于 Hypervisor 下层的部分,从图示中也可以看出,Hypervisor 以上的部分是完全一致的——即提供虚拟化的硬件资源给 Guest OS 来使用。
举个具体的场景,在 Windows 上安装了 VMware 软件,运行了两个 Linux 发行版系统,从而实现某些应用服务的进行。此时,除了应用服务占据开销外,操作系统(2 份!)也占据了硬件资源,因此导致了额外开销。最理想的情况应该是只有应用服务吃掉资源,虚拟机显然没有做到。
究其原因,虚拟机的虚拟化级别太低了,虚拟了整个操作系统。而一些应用服务并不需要从操作系统的程度来模拟,而是安装如 python 或者 node 这样的核心依赖便足够了(当然还有 Linux 系统,但不必为每个应用单独准备,而是共用)。这样 Docker 产生了。
为什么 Docker 好
Docker 基于 Linux 的 namespace, Cgroups 以及 Union File System 等现有能力,为每个容器营造了一个假象,以为自己独占了系统资源(是不是和进程的道理很像?)。
这样如果作图来对比,下图显示了 Type-1 Hypervisor 和 Docker 的结构差异。注意到,左图为每个 App 需要准备一个操作系统出来,而右图的 Docker 只有 Container Engine 这个共用的层级,且都依赖于同一个操作系统(即 Linux),不再需要为每个 App 准备单独的系统出来,因此可以节省空间。

我的理解是,绝大部分的服务都跑在 Linux 下,因此 Docker 选择基于 Linux,因为 Linux 不仅提供了可以隔离容器的技术,也是绝大部分 App 的选择,不必再虚拟化 OS 了。
在 Linux 与 Windows 下运行 Docker 的异同
前文说过,Docker 是基于 Linux 的应用软件,因此必须要有 Linux 系统才能运行。因此,在 Linux 服务器上安装并运行 Docker 非常简单,用喜欢的包管理器安装即可。
然而在 Windows 下,必须有一个 Linux 系统才可以!怎么办?比较方便的方法是启用 WSL2,启用 WSL2 又需要启用 Hyper-V。这样,有了一个 Linux 子系统(那也是 Linux),Docker 便可以在这个系统下进行容器的配置咯。
概念辨析:Hypervisor、Hyper-V、WSL1、WSL2、Linux 发行版
Hypervisor 是虚拟机管理器,是所有基于虚拟机的技术必须有的组分,分为两种,前文已经讲述过。其中 Hyper-V 直接与硬件资源交互,属于第一种。
WSL1 是 Windows 提供的第一代 Linux 子系统。它对于在 Windows 上的 Linux App,将 App 调用的 Linux 指令翻译为和 Windows 内核交互的。所以本质是个翻译器,没有涉及虚拟化。但这样的效果必然不好,并不能提供一个完好的 Linux 系统,这就有了 WSL2。
WSL2 是一个运行在 Hyper-V 上的 Linux 内核。
WSL2 = Windows + Hyper-V + Linux kernel
所以并不能在购买云服务器的时候指定安装一个所谓 WSL2 发行版系统,不存在的。WSL2 只是个内核,在启用 WSL2 后,可以选择发行版。
发行版和内核的关系是,它们都基于同一个 Linux 内核(代码)。为了满足用户群体的不同需求(稳定性、个性化等),不同发行版在用户层次的配置略有不同,但内核是一个!因此,在配置 Docker 镜像的时候,可以选择不同的发行版,没关系,Docker 在核心技术上也不必在意发行版的不同,因为 Docker 的核心技术基于 Linux 内核。
