一、集装箱
-
传统运输业: 在没有集装箱的时代,货物形状、大小不一,装船、卸货极其复杂低效,容易损坏。集装箱出现后,所有货物都被打包进标准尺寸的箱子里,运输工具(船、卡车、火车)也只关心集装箱,而不关心里面的具体货物。
-
Docker 的类比:
-
货物 = 应用程序 + 其依赖(运行环境、库、配置文件等)
-
集装箱 = Docker 镜像
-
码头、轮船、卡车 = 任何支持 Docker 的宿主机器(物理机、虚拟机、云服务器)
-
二、标准化
1、运输方式
就像集装箱定义了全球物流的标准尺寸和吊装接口一样,Docker 定义了软件交付物的标准包装和运输方式。
-
具体体现:
-
打包标准: 无论你的应用是 Java、Python、Node.js 还是 Go 语言编写的,无论它需要什么依赖,最终都被打包成同一种东西------Docker 镜像。
-
运输标准: 这个镜像可以通过
docker pull和docker push命令,像搬运集装箱一样,在开发机、测试服务器、生产服务器以及任何镜像仓库(如 Docker Hub)之间轻松流转。
-
2、存储方式
Docker 镜像并非一个单一的大文件,而是由一系列只读的镜像层 叠加而成的。每一层代表文件系统的一组更改。
-
具体体现:
-
分层构建:
Dockerfile中的每一条指令都会创建一个新的镜像层。FROM ubuntu:20.04 # 层1:基础层
RUN apt-get update && apt-get install -y python3 # 层2:安装软件
COPY . /app # 层3:复制代码
CMD ["python3", "/app/main.py"] # 层4:启动命令
-
-
联合文件系统: 当容器启动时,Docker 会将这些只读层叠加,并在最顶 层加上一个可写的容器层,形成一个统一的文件系统视图。
-
存储共享: 如果多个镜像共享相同的基础层(例如,都是基于
ubuntu:20.04),那么宿主机上只存储一份该层。这极大地节省了磁盘空间和网络传输带宽(拉取新镜像时,只需下载不同的层)。
3、API接口
Docker 为容器的生命周期管理提供了一套统一的 REST API。
-
具体体现:
-
统一的操作命令: 无论容器内部是什么应用,你都可以通过一套统一的 Docker 命令来管理它:
-
docker create/docker run -
docker start/docker stop/docker restart -
docker rm/docker logs/docker exec
-
-
标准化的运行时接口: 这套 API 成为了一个事实上的标准。任何实现了同样接口的容器运行时(如
containerd、podman等)都可以运行 Docker 镜像。 -
生态工具的基石: 更高级的编排工具(如 Kubernetes )并不直接与 Docker 引擎交互,而是通过与
containerd或直接通过 CRI 接口与容器运行时交互,而这一切的接口设计都源于 Docker 确立的范式。Kubernetes 的 Pod、Deployment 等资源,其底层操作容器的逻辑与 Docker 命令的思想一脉相承。
-
三、隔离
Docker 利用 Linux 内核的命名空间和控制组等技术,为每个容器创建独立的运行环境。
-
进程隔离: 容器内的进程与宿主机和其他容器的进程是隔离的。
-
文件系统隔离: 每个容器有自己的根文件系统。
-
网络隔离: 每个容器有自己独立的网络栈和 IP 地址。
-
资源隔离: 可以限制每个容器能使用的 CPU、内存等资源。