Chapter 01

容器化概念与 Docker 架构

理解"在我电脑能跑"问题的根源,掌握容器与虚拟机的本质区别

"在我电脑能跑"问题的根源

这是每个开发者都遇到过的经典困境:你的代码在本机运行完美,但部署到测试或生产服务器后就出错了。根源在于两个方面:

📦
依赖版本不同 本机装的是 Node.js 18,服务器上是 Node.js 14。本机是 Python 3.11,服务器是 Python 3.8。第三方库版本、系统库版本都可能不同。
⚙️
环境配置不同 环境变量、配置文件路径、文件权限、端口占用情况、操作系统版本(甚至 macOS vs Linux 的行为差异)。

传统的解决方案是编写长长的"部署文档",列出所有需要安装的软件和配置步骤。但这种方式脆弱且不可靠——Docker 的出现彻底改变了这一切。

虚拟机 vs 容器

容器不是第一个解决环境隔离问题的技术,虚拟机(VM)更早。了解二者的区别有助于理解容器的价值。

虚拟机架构

物理硬件 (CPU/内存/磁盘)
宿主操作系统 + Hypervisor
Guest OS 1(完整 Linux/Windows)
应用依赖库
应用程序 A

容器架构

物理硬件 (CPU/内存/磁盘)
宿主操作系统内核(共享)
容器运行时(Docker Engine)
应用依赖库(隔离)
应用程序 A
对比维度虚拟机容器
隔离级别完整操作系统隔离进程级隔离(共享宿主内核)
启动时间分钟级(需启动完整 OS)秒级甚至毫秒级
占用空间几 GB(含完整 OS)几十 MB(仅含应用依赖)
性能开销较大(硬件虚拟化)极小(近乎原生)
密度一台宿主机跑数十个 VM一台宿主机跑数百个容器
安全隔离更强(独立内核)较强(共享内核,有逃逸风险)
适用场景不同 OS、强安全隔离微服务、快速部署、CI/CD
💡

它们并不互斥 — 在实际生产中,通常在虚拟机(云服务器)上运行容器。容器提供应用级隔离,虚拟机提供底层安全隔离。

容器技术的底层:Linux 特性

Docker 本身并没有发明什么新技术,它是对 Linux 内核若干已有特性的优雅封装和工具化。

Linux Namespace(命名空间)

Namespace 让每个容器"认为"自己拥有整个系统。Linux 提供多种命名空间:

Control Groups / cgroups(控制组)

Namespace 解决了"看到什么"的问题,cgroups 解决"能用多少"的问题。它限制并统计容器的资源使用:

Union File System(联合文件系统)

容器镜像的分层存储依赖联合文件系统。Docker 默认使用 overlay2 驱动:

镜像基础层(只读)— FROM ubuntu:22.04
镜像层 2(只读)— RUN apt-get install curl
镜像层 3(只读)— COPY app /app
容器可写层(运行时创建,删除容器则消失)

多个容器可以共享同一个只读镜像层,节省磁盘空间,同时写时复制(Copy-on-Write)机制确保各容器的修改互不影响。

Docker 核心概念

Docker 架构:Client-Server 模式

Docker 采用 Client-Server 架构,各组件职责清晰:

# Docker 架构调用链

docker CLI(客户端)
    │  通过 Unix Socket / TCP 发送 REST API 请求
    ▼
dockerd(Docker Daemon)
    │  高层管理:镜像、容器、网络、Volume
    ▼
containerd(OCI 容器运行时管理器)
    │  管理容器的完整生命周期
    ▼
containerd-shim
    │  进程监管,与 containerd 解耦
    ▼
runc(OCI 容器运行时)
    │  实际调用 Linux Namespace + cgroups
    ▼
Linux 内核(Namespace / cgroups / overlayfs)

这种分层架构的好处是:即使 dockerd 重启,正在运行的容器(containerd 管理)不会受影响。

Docker Desktop vs Docker Engine

🖥️
Docker Desktop(Mac / Windows) 包含一个轻量 Linux 虚拟机(因为 Docker 依赖 Linux 内核),GUI 管理界面,自带 Docker Compose 和 Kubernetes。适合开发环境使用,免费用于个人使用。
🐧
Docker Engine(Linux 服务器) 纯命令行,直接运行在 Linux 内核上(无需虚拟机),性能最佳。生产服务器、CI/CD 环境的标准选择,完全开源免费。

镜像分层原理

理解分层是理解 Docker 性能和缓存机制的关键:

# 每条 Dockerfile 指令创建一层
FROM ubuntu:22.04          # 层 1(从 Registry 拉取)
RUN apt-get update           # 层 2(新增文件)
RUN apt-get install -y curl  # 层 3(新增文件)
COPY ./app /app              # 层 4(新增文件)
CMD ["./app"]               # 层 5(仅元数据,不创建文件层)

本章小结 — 容器通过 Linux Namespace 隔离进程视图,通过 cgroups 限制资源,通过 overlay2 共享文件系统层。Docker 是这些技术的工具化封装,让容器变得易于使用和分发。