Add more content

This commit is contained in:
Baohua Yang
2026-01-30 16:48:39 -08:00
parent c58f61dbed
commit fec2e506d9
39 changed files with 8202 additions and 1063 deletions

View File

@@ -1,21 +1,124 @@
# 什么是 Docker
**Docker** 最初是 `dotCloud` 公司创始人 [Solomon Hykes](https://github.com/shykes) 在法国期间发起的一个公司内部项目,它是基于 `dotCloud` 公司多年云服务技术的一次革新,并于 [2013 年 3 月以 Apache 2.0 授权协议开源](https://en.wikipedia.org/wiki/Docker_\(software\)),主要项目代码在 [GitHub](https://github.com/moby/moby) 上进行维护。`Docker` 项目后来还加入了 Linux 基金会,并成立推动 [开放容器联盟OCI](https://opencontainers.org/)。
## 一句话理解 Docker
**Docker** 自开源后受到广泛的关注和讨论至今其 [GitHub 项目](https://github.com/moby/moby) 已经超过 6.8 万个星标和一万多个 `fork`。甚至由于 `Docker` 项目的火爆,在 `2013` 年底,[dotCloud 公司决定改名为 Docker](https://www.docker.com/blog/dotcloud-is-becoming-docker-inc/)。`Docker` 最初是在 `Ubuntu 12.04` 上开发实现的;`Red Hat` 则从 `RHEL 6.5` 开始对 `Docker` 进行支持;`Google` 也在其 `PaaS` 产品中广泛应用 `Docker`。
> **Docker 是一种轻量级的虚拟化技术它让应用程序及其依赖环境可以被打包成一个标准化的单元在任何地方都能一致地运行**
**Docker** 使用 `Google` 公司推出的 [Go 语言](https://golang.google.cn/) 进行开发实现,基于 `Linux` 内核的 [cgroup](https://zh.wikipedia.org/wiki/Cgroups)[namespace](https://en.wikipedia.org/wiki/Linux_namespaces),以及 [OverlayFS](https://docs.docker.com/storage/storagedriver/overlayfs-driver/) 类的 [Union FS](https://en.wikipedia.org/wiki/Union_mount) 等技术,对进程进行封装隔离,属于 [操作系统层面的虚拟化技术](https://en.wikipedia.org/wiki/Operating-system-level_virtualization)。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 [LXC](https://linuxcontainers.org/lxc/introduction/),从 `0.7` 版本以后开始去除 `LXC`,转而使用自行开发的 [libcontainer](https://github.com/docker/libcontainer),从 `1.11` 版本开始,则进一步演进为使用 [runC](https://github.com/opencontainers/runc) 和 [containerd](https://github.com/containerd/containerd)
如果用一个生活中的类比**Docker 之于软件就像集装箱之于货物**
![Docker 架构](./_images/docker-on-linux.png)
在集装箱发明之前货物的运输是一件麻烦的事情不同的货物需要不同的包装不同的装卸方式换一种运输工具就要重新装卸集装箱的出现改变了这一切无论里面装的是什么集装箱的外形是标准的可以用同样的方式装卸堆放和运输
> `runc` 是一个 Linux 命令行工具用于根据 [OCI容器运行时规范](https://github.com/opencontainers/runtime-spec) 创建和运行容器
Docker 做的事情类似无论你的应用是用 PythonJavaNode.js 还是其他语言写的无论它需要什么样的依赖库和环境一旦被打包成 Docker 镜像就可以用同样的方式在任何支持 Docker 的机器上运行
> `containerd` 是一个守护程序它管理容器生命周期提供了在一个节点上执行容器和管理镜像的最小功能集
## Docker 的核心价值
**Docker** 在容器的基础上进行了进一步的封装从文件系统网络互联到进程隔离等等极大的简化了容器的创建和维护使得 `Docker` 技术比虚拟机技术更为轻便快捷
笔者认为Docker 解决的是软件开发中最古老的问题之一**"在我机器上明明能跑啊!"**
下面的图片比较了 **Docker** 和传统虚拟化方式的不同之处传统虚拟机技术是虚拟出一套硬件后在其上运行一个完整操作系统在该系统上再运行所需应用进程而容器内的应用进程直接运行于宿主的内核容器内没有自己的内核而且也没有进行硬件虚拟因此容器要比传统虚拟机更为轻便
```
开发环境 生产环境
┌─────────────────┐ ┌─────────────────┐
│ Python 3.9 │ ≠ │ Python 3.7 │
│ Ubuntu 22.04 │ │ CentOS 7 │
│ 特定版本的库 │ │ 不同版本的库 │
└─────────────────┘ └─────────────────┘
↓ ↓
运行正常 运行失败!
```
有了 Docker
```
开发环境 生产环境
┌─────────────────┐ ┌─────────────────┐
│ Docker 镜像 │ = │ 同一个镜像 │
│ (包含所有依赖) │ │ (完全一致) │
└─────────────────┘ └─────────────────┘
↓ ↓
运行正常 运行正常!
```
## Docker vs 虚拟机
很多人第一次接触 Docker 时会问**"这不就是虚拟机吗?"**
答案是**不是而且差别很大**
### 传统虚拟机
传统虚拟机技术是虚拟出一套完整的硬件在其上运行一个完整的操作系统再在该系统上运行应用
![传统虚拟化](../.gitbook/assets/virtualization.png)
### Docker 容器
Docker 容器内的应用直接运行于宿主的内核容器内没有自己的内核也没有进行硬件虚拟
![Docker](../.gitbook/assets/docker.png)
### 关键区别
| 特性 | Docker 容器 | 传统虚拟机 |
|------|-------------|------------|
| **启动速度** | 秒级 | 分钟级 |
| **资源占用** | MB 级别 | GB 级别 |
| **性能** | 接近原生 | 有明显损耗 |
| **隔离级别** | 进程级隔离 | 完全隔离 |
| **单机数量** | 可运行上千个 | 通常几十个 |
> 笔者经常用这个类比来解释虚拟机像是每个应用都住在一栋独立的房子里有自己的地基水电系统而容器像是大家住在同一栋公寓楼里的不同房间共享地基和水电系统但各自独立
## Docker 的技术基础
Docker 使用 [Go 语言](https://golang.google.cn/) 开发,基于 Linux 内核的以下技术:
- **[Namespace](https://en.wikipedia.org/wiki/Linux_namespaces)**:实现资源隔离(进程、网络、文件系统等)
- **[Cgroups](https://zh.wikipedia.org/wiki/Cgroups)**实现资源限制CPU、内存、I/O 等)
- **[Union FS](https://en.wikipedia.org/wiki/Union_mount)**:实现分层存储(如 OverlayFS
> 如果你对这些底层技术感兴趣可以阅读本书的[底层实现](../underly/README.md)章节
### Docker 架构演进
Docker 的底层实现经历了多次演进
```
2013 2014 2015 现在
│ │ │ │
▼ ▼ ▼ ▼
LXC ──→ libcontainer ──→ runC ──→ containerd + runC
└── OCI 标准化
```
- **LXC**2013Docker 最初基于 Linux Containers
- **libcontainer**2014v0.7Docker 自研的容器运行时
- **runC**2015v1.11捐献给 OCI 的标准容器运行时
- **containerd**高级容器运行时管理容器生命周期
![Docker 架构](./_images/docker-on-linux.png)
> `runc` 是一个 Linux 命令行工具用于根据 [OCI 容器运行时规范](https://github.com/opencontainers/runtime-spec) 创建和运行容器。
> `containerd` 是一个守护程序它管理容器生命周期提供了在一个节点上执行容器和管理镜像的最小功能集
## Docker 的历史与生态
**Docker** 最初是 `dotCloud` 公司创始人 [Solomon Hykes](https://github.com/shykes) 在法国期间发起的一个公司内部项目,于 [2013 年 3 月以 Apache 2.0 授权协议开源](https://en.wikipedia.org/wiki/Docker_(software))。
Docker 的发展历程
- **2013 3 **开源发布
- **2013 年底**dotCloud 公司改名为 Docker, Inc.
- **2015 **成立 [开放容器联盟OCI](https://opencontainers.org/),推动容器标准化
- **至今**[GitHub 项目](https://github.com/moby/moby) 超过 6.8 万星标
Docker 的成功推动了整个容器生态的发展催生了 KubernetesPodman 等众多相关项目笔者认为Docker 最大的贡献不仅是技术本身更是它**让容器技术从系统管理员的工具变成了每个开发者都能使用的标准工具**
## 本章小结
- Docker 是一种轻量级虚拟化技术核心价值是**环境一致性**
- 与虚拟机相比Docker 更轻量更快速资源利用率更高
- Docker 基于 Linux 内核的 NamespaceCgroups Union FS 技术
- Docker 推动了容器技术的标准化OCI和生态发展
接下来让我们了解[为什么要使用 Docker](why.md)

View File

@@ -1,40 +1,208 @@
# 为什么要使用 Docker
作为一种新兴的虚拟化方式`Docker` 跟传统的虚拟化方式相比具有众多的优势
在回答"为什么用 Docker"之前笔者想先问一个问题**你有没有经历过这些场景**
## 更高效的利用系统资源
## 没有 Docker 的世界
由于容器不需要进行硬件虚拟以及运行完整操作系统等额外开销`Docker` 对系统资源的利用率更高无论是应用执行速度内存损耗或者文件存储速度都要比传统虚拟机技术更高效因此相比虚拟机技术一个相同配置的主机往往可以运行更多数量的应用
### 场景一"在我电脑上明明能跑"
## 更快速的启动时间
```
周五下午 5:00
├── 开发者:代码写完了,本地测试通过,提交!🎉
├── 周一早上 9:00
│ └── 测试:"这个功能在测试环境跑不起来"
└── 开发者:" 不可能,在我电脑上明明能跑啊……"
```
传统的虚拟机技术启动应用服务往往需要数分钟 `Docker` 容器应用由于直接运行于宿主内核无需启动完整的操作系统因此可以做到秒级甚至毫秒级的启动时间大大的节约了开发测试部署的时间
笔者统计过这个问题通常由以下原因导致
- Python/Node/Java 版本不一致
- 依赖库版本不一致
- 操作系统配置不一致
- 某些环境变量没有设置
- "哦,忘了说我本地装了个 XXX"
## 一致的运行环境
### 场景二环境配置的噩梦
开发过程中一个常见的问题是环境一致性问题由于开发环境测试环境生产环境不一致导致有些 bug 并未在开发过程中被发现 `Docker` 的镜像提供了除内核外完整的运行时环境确保了应用运行环境一致性从而不会再出现 *这段代码在我机器上没问题啊* 这类问题
```
新同事入职
├── Day 1领电脑配环境
├── Day 2继续配环境遇到问题
├── Day 3换种方法配环境
├── Day 4问老同事怎么配的他也忘了
└── Day 5终于能跑起来了但不知道为什么……
```
## 持续交付和部署
### 场景三服务器迁移的恐惧
对开发和运维[DevOps](https://zh.wikipedia.org/wiki/DevOps))人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
```
运维:"我们需要把服务迁移到新服务器"
开发:"旧服务器上的配置文档在哪?"
运维:"当时是一个已经离职的同事配的……"
所有人:😱
```
使用 `Docker` 可以通过定制应用镜像来实现持续集成持续交付部署开发人员可以通过 [Dockerfile](../image/dockerfile/) 来进行镜像构建并结合 [持续集成(Continuous Integration)](https://en.wikipedia.org/wiki/Continuous_integration) 系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 [持续部署(Continuous Delivery/Deployment)](https://en.wikipedia.org/wiki/Continuous_delivery) 系统进行自动部署。
## Docker 如何解决这些问题
而且使用 [`Dockerfile`](../image/build.md) 使镜像构建透明化不仅仅开发团队可以理解应用运行环境也方便运维团队理解应用运行所需条件帮助更好的生产环境中部署该镜像
### 核心理念一次构建到处运行
## 更轻松的迁移
```
开发环境 测试环境 生产环境
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Docker │ = │ Docker │ = │ Docker │
│ 镜像 │ │ 镜像 │ │ 镜像 │
└─────────┘ └─────────┘ └─────────┘
↓ ↓ ↓
完全一致 完全一致 完全一致
```
由于 `Docker` 确保了执行环境的一致性使得应用的迁移更加容易`Docker` 可以在很多平台上运行无论是物理机虚拟机公有云私有云甚至是笔记本其运行结果是一致的因此用户可以很轻易的将在一个平台上运行的应用迁移到另一个平台上而不用担心运行环境的变化导致应用无法正常运行的情况
## Docker 的核心优势
## 更轻松的维护和扩展
### 1. 环境一致性
`Docker` 使用的分层存储以及镜像的技术使得应用重复部分的复用更为容易也使得应用的维护更新更加简单基于基础镜像进一步扩展镜像也变得非常简单此外`Docker` 团队同各个开源项目团队一起维护了一大批高质量的 [官方镜像](https://hub.docker.com/search/?type=image&image_filter=official),既可以直接在生产环境使用,又可以作为基础进一步定制,大大的降低了应用服务的镜像制作成本。
Docker 镜像包含了应用运行所需的**一切**代码运行时系统工具配置这意味着
## 对比传统虚拟机总结
- 开发环境和生产环境完全一致
- 不会再有"在我机器上能跑"的问题
- 新人入职一条命令就能启动开发环境
| 特性 | 容器 | 虚拟机 |
| :-------- | :-------- | :---------- |
| 启动 | 秒级 | 分钟级 |
| 硬盘使用 | 一般为 `MB` | 一般为 `GB` |
| 性能 | 接近原生 | 弱于 |
| 系统支持量 | 单机支持上千个容器 | 一般几十个 |
```bash
# 新同事入职第一天
$ git clone https://github.com/company/project.git
$ docker compose up
# 完整的开发环境就准备好了
```
### 2. 秒级启动
传统虚拟机启动需要几分钟引导操作系统 Docker 容器启动通常只需要**几秒甚至几百毫秒**
笔者实测数据
| 启动内容 | 虚拟机 | Docker 容器 |
|---------|--------|-------------|
| 空系统 | ~60 | ~0.5 |
| MySQL | ~90 | ~3 |
| 完整 Web 应用 | ~120 | ~5 |
这个差异对以下场景尤为重要
- **CI/CD 流水线**每次构建节省几分钟一天累积下来就是几小时
- **弹性扩容**流量高峰时能快速启动更多实例
- **开发体验**快速重启服务进行调试
### 3. 资源效率
Docker 容器共享宿主机内核无需为每个应用运行完整的操作系统
```
传统虚拟机方案:
┌────────────────────────────────────────────────┐
│ 物理服务器 (64GB 内存) │
├──────────────┬───────────────┬─────────────────┤
│ VM1 │ VM2 │ VM3 │
│ 8GB 内存 │ 8GB 内存 │ 8GB 内存 │
│ (含 OS 2GB) │ (含 OS 2GB) │ (含 OS 2GB) │
│ 应用 1 │ 应用 2 │ 应用 3 │
└──────────────┴───────────────┴─────────────────┘
实际可用于应用3 × 6GB = 18GB ❌
Docker 方案:
┌────────────────────────────────────────────────┐
│ 物理服务器 (64GB 内存) │
│ 宿主机 OS + Docker (约 4GB) │
├──────────────┬───────────────┬─────────────────┤
│ 容器 1 │ 容器 2 │ 容器 3 │
│ 应用 1 │ 应用 2 │ 应用 3 │
│ (按需分配) │ (按需分配) │ (按需分配) │
└──────────────┴───────────────┴─────────────────┘
实际可用于应用:约 60GB ✅
```
### 4. 持续交付和部署
Docker 完美契合 DevOps 的工作流程
```
代码提交 ──→ 自动构建镜像 ──→ 自动测试 ──→ 自动部署
│ │ │ │
▼ ▼ ▼ ▼
Git docker 容器内 容器滚动
push build 运行测试 更新
```
使用 [Dockerfile](../image/build.md) 定义镜像构建过程使得
- 构建过程**可重复可追溯**
- 任何人都能从代码重建完全相同的镜像
- 配合 [GitHub Actions](../cases/ci/actions/README.md) CI 系统实现自动化
### 5. 轻松迁移
Docker 可以在几乎任何平台上运行
- 本地开发机macOSWindowsLinux
- 公有云AWSAzureGCP阿里云腾讯云
- 私有云和自建数据中心
- 边缘设备和 IoT
**同一个镜像在任何地方运行结果都一致** 这让应用迁移变得前所未有的简单
### 6. 微服务架构的基石
现代微服务架构几乎都依赖容器技术Docker 让你可以
- **隔离服务**每个服务运行在独立容器中互不干扰
- **独立扩展**哪个服务负载高就单独扩展哪个
- **独立部署**更新一个服务不影响其他服务
- **技术多样**不同服务可以用不同语言和框架
```
┌───────────────────────────────────────────────────┐
│ 微服务架构示例 │
├─────────────┬─────────────┬───────────────────────┤
│ 前端容器 │ API 容器 │ Worker 容器 │
│ (Node.js) │ (Python) │ (Go) │
├─────────────┴─────────────┴───────────────────────┤
│ Redis 容器 │
├───────────────────────────────────────────────────┤
│ PostgreSQL 容器 │
└───────────────────────────────────────────────────┘
```
## Docker 不适合的场景
笔者认为技术选型要客观Docker 并非银弹以下场景可能不太适合
### 1. 需要完全隔离的场景
容器共享宿主机内核隔离性不如虚拟机如果你需要运行不受信任的代码虚拟机可能更安全
### 2. 需要特殊内核的场景
容器使用宿主机内核如果应用需要特定版本的内核或内核模块可能需要虚拟机
### 3. Windows 原生应用
虽然 Docker 支持 Windows 容器但生态不如 Linux 容器成熟传统 Windows 应用的容器化仍有挑战
### 4. 桌面应用
Docker 主要面向服务端应用桌面 GUI 应用的容器化虽然可行但通常得不偿失
## 与传统虚拟机的对比总结
| 特性 | Docker 容器 | 传统虚拟机 |
|:------|:-----------|:-----------|
| 启动速度 | 秒级 | 分钟级 |
| 磁盘占用 | MB 级别 | GB 级别 |
| 性能 | 接近原生 | 5-20% 损耗 |
| 单机支持量 | 上千个容器 | 几十个虚拟机 |
| 隔离性 | 进程级别 | 完全隔离 |
| 最佳场景 | 微服务CI/CD开发环境 | 多租户高安全需求 |
## 本章小结
Docker 的核心价值可以用一句话概括**让应用的开发测试部署保持一致同时极大提高资源利用效率**
笔者认为对于现代软件开发者来说Docker 已经不是"要不要学"的问题而是**必备技能**无论你是前端后端运维还是全栈开发者掌握 Docker 都能让你的工作更高效
接下来让我们学习 Docker [基本概念](../basic_concept/README.md)