01 - Docker 是什么?容器 vs 虚拟机
从问题出发:为什么需要容器?
在传统开发中,我们经常遇到这些问题:
- "在我机器上能跑啊" —— 环境不一致
- 部署一个应用需要手动安装各种依赖
- 不同应用之间的依赖可能冲突(比如 Python 2 vs Python 3)
- 资源利用率低,一台服务器只跑一个应用太浪费
容器技术就是为了解决这些问题而生的。
核心概念
容器 (Container)
容器是一个轻量级的、独立的运行环境,它把应用和所有依赖打包在一起。可以类比为一个"标准化的集装箱"——不管里面装什么货物,外面的运输系统(船、卡车)都能用统一的方式搬运。
镜像 (Image)
镜像是容器的模板/蓝图,是只读的。就像面包的模具——你用一个模具可以做出很多个面包(容器),但模具本身不会变。
Docker
Docker 是目前最流行的容器运行时和管理工具。它不是唯一的容器技术,但它是最成功的。
容器 vs 虚拟机
┌───────────────────────────────────────────────────────┐
│ 虚拟机 (VM) │ 容器 │
├───────────────────────────────────────────────────────┤
│ │ │
│ ┌─────┐ ┌─────┐ ┌─────┐ │ ┌───┐ ┌───┐ ┌───┐│
│ │App A│ │App B│ │App C│ │ │App│ │App│ │App││
│ ├─────┤ ├─────┤ ├─────┤ │ │ A │ │ B │ │ C ││
│ │Bins │ │Bins │ │Bins │ │ ├───┤ ├───┤ ├───┤│
│ │Libs │ │Libs │ │Libs │ │ │Bins│ │Bins│ │Bins│
│ ├─────┤ ├─────┤ ├─────┤ │ │Libs│ │Libs│ │Libs│
│ │Guest│ │Guest│ │Guest│ │ └───┘ └───┘ └───┘│
│ │ OS │ │ OS │ │ OS │ │ ┌───────────────┐ │
│ └─────┘ └─────┘ └─────┘ │ │ Docker Engine│ │
│ ┌───────────────────────┐ │ └───────────────┘ │
│ │ Hypervisor │ │ │
│ └───────────────────────┘ │ │
│ ┌───────────────────────┐ │ ┌───────────────┐ │
│ │ Host OS │ │ │ Host OS │ │
│ └───────────────────────┘ │ └───────────────┘ │
│ ┌───────────────────────┐ │ ┌───────────────┐ │
│ │ Hardware │ │ │ Hardware │ │
│ └───────────────────────┘ │ └───────────────┘ │
└───────────────────────────────────────────────────────┘关键区别
| 特性 | 虚拟机 | 容器 |
|---|---|---|
| 隔离级别 | 硬件级别(Hypervisor) | 进程级别(OS 内核) |
| 操作系统 | 每个 VM 有完整 Guest OS | 共享 Host OS 内核 |
| 启动时间 | 分钟级 | 秒级甚至毫秒级 |
| 体积 | GB 级 | MB 级 |
| 性能开销 | 较大(需要模拟硬件) | 极小(原生进程) |
| 密度 | 一台机器通常跑 10-20 个 VM | 一台机器可以跑 100+ 容器 |
| 安全性 | 更强(完全隔离) | 相对较弱(共享内核) |
一句话总结
- 虚拟机:模拟整台电脑,重但隔离性强
- 容器:隔离进程,轻量快速但共享内核
Docker 架构
Docker 采用 Client-Server 架构:
┌─────────────┐ REST API ┌──────────────────────────────┐
│ │ ◄───────────────► │ Docker Daemon │
│ Docker │ │ (dockerd) │
│ CLI │ │ │
│ (client) │ │ ┌──────────┐ ┌──────────┐ │
│ │ │ │ Images │ │Containers│ │
└─────────────┘ │ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Volumes │ │ Networks │ │
│ └──────────┘ └──────────┘ │
└──────────────────────────────┘
│
▼
┌──────────────────┐
│ Docker Registry │
│ (Docker Hub等) │
└──────────────────┘三大核心组件
Docker Client (docker CLI)
- 用户与 Docker 交互的入口
- 发送命令给 Docker Daemon
Docker Daemon (dockerd)
- Docker 的核心服务进程
- 负责构建、运行和管理容器
- 管理镜像、网络、存储卷
Docker Registry
- 存储 Docker 镜像的仓库
- Docker Hub 是默认的公共仓库
- 可以搭建私有 Registry
Docker 底层技术(Linux 内核特性)
Docker 不是凭空创造的"魔法",它依赖两个关键的 Linux 内核特性:
1. Namespace(命名空间)—— 隔离
让每个容器认为自己是独立的系统:
| Namespace | 隔离内容 |
|---|---|
| PID | 进程 ID,容器内 PID 1 是自己的 init 进程 |
| NET | 网络栈,容器有自己的 IP、端口、路由表 |
| MNT | 文件系统挂载点 |
| UTS | 主机名和域名 |
| IPC | 进程间通信 |
| USER | 用户和组 ID |
2. Cgroups(控制组)—— 资源限制
限制容器能使用多少资源:
- CPU 时间
- 内存上限
- 磁盘 I/O
- 网络带宽
3. UnionFS(联合文件系统)—— 分层镜像
Docker 镜像是分层的,多个只读层叠加 + 一个可写层:
┌─────────────────────┐
│ Container Layer │ ← 可写层(容器运行时修改都在这层)
│ (Read-Write) │
├─────────────────────┤
│ Image Layer 3 │ ← 应用代码 (COPY . /app)
├─────────────────────┤
│ Image Layer 2 │ ← 依赖安装 (RUN pip install)
├─────────────────────┤
│ Image Layer 1 │ ← 基础镜像 (FROM python:3.11)
└─────────────────────┘分层的好处:多个容器可以共享底层镜像层,节省磁盘空间和拉取时间。
关键术语速查
| 术语 | 含义 |
|---|---|
| Image | 只读模板,包含运行应用所需的一切 |
| Container | Image 的运行实例,可以启停删除 |
| Dockerfile | 构建 Image 的脚本文件 |
| Registry | 存储和分发 Image 的服务 |
| Tag | Image 的版本标签,如 python:3.11-slim |
| Layer | Image 的一个只读文件系统层 |
| Volume | 持久化数据存储,容器删除后数据仍在 |
