The Docker Story - Part1: Docker History
docCloud - 也就是开发 Docker 的公司, 最初是一家 PaaS(平台即服务)公司, 他们在 PaaS 领域并没有太大的成功, 但他们构建了一个可以无缝管理客户系统与架构的工具: Docker. 2013 年, 他们决定放弃 PaaS 服务, 将全部精力投入到 Docker 这款产品上.
Containers 容器
Docker 公司并没有发明容器这个概念. 实际上, 容器的概念已经演进了十多年, 很多参与者都做出了贡献, Linux 基金会和 Google 是推动整个生态走向成熟的重要力量.
假如你在运营一家公司, 希望将应用上线, 以前需要做的事大概是:
- 购买一台服务器
- 安装所有必要的应用和依赖
- 配置环境以匹配你的开发设置
- 部署应用
- 把服务器对外开放
看起来很简单, 但实际操作会很复杂:
- 要手动跟踪并更新每个依赖和配置
- 如果出问题, 需要手动去修复
- 基础设施团队需要估算服务器规格(内存、CPU 等) — 为了防止流量高峰崩溃, 通常会配置更高的规格(过度配置)
- 那台高配服务器大多数时间只是闲置着, 做最少量的工作
- 不能轻易扩展或在同一服务器上运行多个应用, 因为每个应用都需要独立的运行环境
总之, 非常混乱
后来出现了虚拟机(VM), 情况有了改善. 使用 VM 可以:
- 在同一台服务器上运行多个隔离的环境
- 为 VM 做快照并在不同服务器间复用
- 不再重复重复地搭建环境,这是一个很大的进步
但 VM 也有缺点:
- 重量级: 每个 VM 需要完整的操作系统,占用大量内存、CPU 和存储
- 性能开销大: 运行多个操作系统实例会带来额外开销, 性能相对较差
- 启动慢: 每个 VM 都需要启动自己的操作系统
- 占用空间多: 完整的操作系统镜像占用大量磁盘空间
于是容器出现了 — 它带来了颠覆性的改变
容器是应用的轻量级、可移植打包. 它包含:
- 你的应用
- 应用的所有依赖(库、二进制文件等)
- 配置文件
- 环境变量
- 运行所需的其他数据
容器非常灵活. 你可以有一个带最精简 Ubuntu 的容器, 另一个容器装 Node.js 应用, 或任何你需要的组合.
容器被设计得尽可能精简, 剔除了诸如 GUI、驱动等不必要项, 从而保持轻量.
真正的关键是: 容器共享宿主机的操作系统内核(host OS kernel).
不同于 VM, 容器不需要自己的完整操作系统, 这节省了大量资源.
举例来说, 如果一台服务器能跑 10 个 VM, 那么同样的机器可能能跑 50 个容器, 这是性能与效率的巨大跃升
The Open Container Initiative (OCI) 开放容器倡议
OCI 由 Google、Linux 基金会和 Docker, Inc. 的人员发起, 定义了一些关键标准, 包括:
- 镜像规范(Image Specification / Image-Spec): 定义容器镜像如何创建
- 运行时规范(Runtime Specification / Runtime-Spec): 标准化容器如何被执行和管理生命周期
- 分发规范(Distribution Specification / Distribution-Spec): 定义容器镜像如何共享与分发
这些规范保证了任何系统能以一致的方式创建、运行和管理容器
The Cloud Native Computing Foundation (CNCF) 云原生计算基金会
CNCF 成立于 2015 年, 使命是推动容器技术并让云原生计算成为现实. 它不像 OCI 那样直接制定标准, 而是专注于帮助与容器相关的项目成长并达到可投入生产的成熟度.
CNCF 项目一般经历三个阶段:
- Sandbox 沙箱: 实验性项目的试验场
- Incubation 孵化: 对有前景的项目进行积极开发和完善
- Graduation 毕业: 达到标准并可用于生产环境
当一个项目"毕业"时, 公司会知道它已经可靠到可以在自身基础设施上使用. 一个典型例子是 Kubernetes, 它作为 CNCF 项目成长, 现已成为现代基础设施的基石.
The Docker Inc, The Docker Platform
正如前面提到的, dotCloud 放弃了 PaaS,把重心放到 Docker, 并更名为 Docker, Inc. 他们把工具集称为 Docker Platform, Docker 平台主要由两大部分组成: 客户端(Client)和引擎(Engine). Docker 客户端(命令行界面 CLI)是与 Docker 引擎交互的方式.
Docker CLI
Docker CLI 是一组命令和指令, 用来与 Docker 引擎交互. 它通过提供一个对复杂内部系统的友好抽象来简化操作, Docker CLI 通过 gRPC API 与 Docker 引擎通信. 基本上, CLI 会把我们的命令(例如 docker ps、docker start、docker stop 等)翻译成 gRPC 请求并发送给 Docker 引擎, 然后再把执行结果以可读的形式显示在终端上.
Docker Engine
Docker 引擎是实际执行工作的地方. 它是一个模块化的应用, 包含许多关键组件. 把它想象成汽车发动机: 大多数人不知道引擎内部的具体细节, 但它能无缝工作. 类似地, 作为用户我们通过 CLI 与 Docker 引擎交互, 指示它去执行各种动作, 而不必了解内部所有细节. 然而, 要深入理解 Docker, 了解引擎内部发生了什么是很重要的.
Docker 引擎向客户端暴露了一个 API 层, 客户端使用该 API 把命令转成 gRPC 调用并与服务器交互. Docker 引擎封装了创建、运行与管理容器所需的全部复杂性. 值得一提的是, Docker 引擎和 Docker CLI 都是用 Golang 语言编写的.