Docker 是一种轻量级的虚拟化技术,它让应用程序及其依赖环境可以被打包成一个标准化的单元,在任何地方都能一致地运行。
如果用一个生活中的类比:Docker 之于软件,就像集装箱之于货物。
在集装箱发明之前,货物的运输是一件麻烦的事情——不同的货物需要不同的包装、不同的装卸方式,换一种运输工具就要重新装卸。集装箱的出现改变了这一切:无论里面装的是什么,集装箱的外形是标准的,可以用同样的方式装卸、堆放和运输。
Docker 做的事情类似:无论你的应用是用 Python、Java、Node.js 还是其他语言写的,无论它需要什么样的依赖库和环境,一旦被打包成 Docker 镜像,就可以用同样的方式在任何支持 Docker 的机器上运行。
笔者认为,Docker 解决的是软件开发中最古老的问题之一:"在我机器上明明能跑啊!"
开发环境 生产环境
┌─────────────────┐ ┌─────────────────┐
│ Python 3.14 │ ≠ │ Python 3.11 │
│ Ubuntu 24.04 │ │ Ubuntu 22.04 │
│ 特定版本的库 │ │ 不同版本的库 │
└─────────────────┘ └─────────────────┘
↓ ↓
运行正常 运行失败!
有了 Docker:
开发环境 生产环境
┌─────────────────┐ ┌─────────────────┐
│ Docker 镜像 │ = │ 同一个镜像 │
│ (包含所有依赖) │ │ (完全一致) │
└─────────────────┘ └─────────────────┘
↓ ↓
运行正常 运行正常!
很多人第一次接触 Docker 时会问:"这不就是虚拟机吗?"
答案是:不是,而且差别很大。
传统虚拟机技术是虚拟出一套完整的硬件,在其上运行一个完整的操作系统,再在该系统上运行应用:
而 Docker 容器内的应用直接运行于宿主的内核,容器内没有自己的内核,也没有进行硬件虚拟:
笔者经常用这个类比来解释:虚拟机像是每个应用都住在一栋独立的房子里(有自己的地基、水电系统),而容器像是大家住在同一栋公寓楼里的不同房间(共享地基和水电系统,但各自独立)。
Docker 使用 Go 语言 开发,基于 Linux 内核的以下技术:
如果你对这些底层技术感兴趣,可以阅读本书的底层实现章节。
Docker 的底层实现经历了多次演进:
LXC(2013):Docker 最初基于 Linux Containers
libcontainer(2014,v0.7):Docker 自研的容器运行时
runC(2015,v1.11):捐献给 OCI 的标准容器运行时
containerd:高级容器运行时,管理容器生命周期
runc 是一个 Linux 命令行工具,用于根据 OCI 容器运行时规范 创建和运行容器。
containerd 是一个守护程序,它管理容器生命周期,提供了在一个节点上执行容器和管理镜像的最小功能集。
Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,于 2013 年 3 月以 Apache 2.0 授权协议开源。
Docker 的发展历程:
2013 年底:dotCloud 公司改名为 Docker, Inc.
Docker 的成功推动了整个容器生态的发展,催生了 Kubernetes、Podman 等众多相关项目。笔者认为,Docker 最大的贡献不仅是技术本身,更是它让容器技术从系统管理员的工具变成了每个开发者都能使用的标准工具。
Docker 是一种轻量级虚拟化技术,核心价值是环境一致性
与虚拟机相比,Docker 更轻量、更快速、资源利用率更高
Docker 基于 Linux 内核的 Namespace、Cgroups 和 Union FS 技术
Docker 推动了容器技术的标准化(OCI)和生态发展
接下来,让我们了解为什么要使用 Docker。