Docker镜像概述与生命周期
咱们做容器化,第一件事就是搞明白镜像是什么。
说白了,Docker 镜像就是一个轻量的、可执行的独立软件包。它包含了运行某个应用所需的一切——代码、运行时、系统工具、系统库、设置。我个人习惯把镜像理解成“一个文件系统的快照 + 一些元数据”。
你想想看,有了镜像,你在任何地方都能拉起一个一模一样的运行环境。这就是容器一致性的基础。
镜像 vs. 虚拟机镜像
很多新手问我:“Docker 镜像和 VM 镜像有啥区别?” 嗯,差别挺大的。我整理了一个表格,方便你对比:
| 特性 | Docker 镜像 | 虚拟机镜像 |
|---|---|---|
| 大小 | 通常 MB ~ GB 级别 | 通常 GB ~ TB 级别 |
| 启动速度 | 秒级 | 分钟级 |
| 内核 | 共享宿主机内核 | 包含独立内核 |
| 分层结构 | 是(分层构建、复用) | 否(通常为单层文件) |
| 可移植性 | 极高(OCI 标准) | 较低(依赖 Hypervisor) |
| 隔离级别 | 进程级隔离 | 硬件级虚拟化 |
你看,Docker 镜像没有自己的内核,它就是一堆文件。这带来了极快的启动和极小的体积。我在项目中遇到过好几次,用 VM 镜像部署测试环境,光下载就得等半天。换成 Docker 镜像后,几秒钟就拉下来了。
镜像的核心生命周期
一个 Docker 镜像从出生到消亡,大致经历这些阶段:
- 构建 (Build):通过 Dockerfile 创建镜像。
- 保存 (Save/Load):将镜像导出为 tar 文件,或从 tar 文件导入。
- 推送 (Push):上传到镜像仓库。
- 拉取 (Pull):从仓库下载到本地。
- 运行 (Run):基于镜像创建并启动容器。
- 删除 (Rmi):从本地移除镜像层。
别小看这个流程。我曾经在一个生产事故里,就是因为没搞清楚“镜像层”和“容器层”的差异,导致日志丢了。后面我会细讲。
镜像的构成:分层文件系统
Docker 镜像是由一层层只读文件系统叠加而成的。每一层代表一个 Dockerfile 指令。
举个例子,看这个 Dockerfile:
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
COPY app.py /app/
CMD ["python3", "/app/app.py"]
构建时,Docker 会为 FROM、RUN、COPY 各生成一层。这些层是只读的,并且可以复用。比如你本地已经有了 ubuntu:22.04 的层,下次构建时它就直接复用,不用再下载。
为什么要有分层?说白了就是为了节省空间和传输时间。你想想看,如果每个镜像都打成一个巨大的单体文件,那下载一个 MySQL 镜像就得重新下载整个操作系统,多浪费。
小技巧: 使用 docker history 命令可以查看镜像的分层信息和每层的大小。
docker history nginx:latest
注意: 镜像层是只读的。容器启动时会在镜像层之上挂载一个可写层(容器层)。你在容器内做的任何修改,比如创建文件、修改配置,都写入这个可写层。一旦容器被删除,这个可写层也会消失。所以重要的数据一定要用数据卷(Volume)持久化。
镜像的元数据
镜像不光有文件系统,还有元数据。这些信息记录了镜像的“身世”。
用 docker inspect 可以看到完整的元数据,包括:
- 镜像 ID:唯一标识。
- 创建时间:构建时间戳。
- 架构/操作系统:例如 linux/amd64。
- Entrypoint / Cmd:容器启动时执行的命令。
- 环境变量:预置的
ENV。 - 暴露端口:如
EXPOSE 80。 - 数据卷配置:
VOLUME指令声明的挂载点。
这些信息对“校验”至关重要。我们后面会反复用到 docker inspect 来对比镜像与容器的一致性。
镜像仓库管理与标签规范
镜像光在本地不行,得上仓库。Docker Hub、私有 Registry、Harbor、AWS ECR 等等。
我个人经验是:一定要用有意义的标签,千万别用 latest 当版本号。我在一个项目里接手了一个用 latest 打标签的 CI/CD 系统,结果每次构建完,谁也不知道线上跑的是哪天的代码。后来我们统一规范了:
# 推荐格式
[仓库地址]/[项目名]/[镜像名]:[版本号]-[构建序号]
example.com/myapp/backend:v1.2.3-b45
# 或者使用 Git Commit SHA
example.com/myapp/backend:git-a1b2c3d
| 标签类型 | 例子 | 适用场景 | 风险 |
|---|---|---|---|
| 语义版本 | v1.2.3 |
正式发布 | 低 |
| Git SHA | git-a1b2c3d |
CI/CD 构建产物 | 极低 |
latest |
latest |
开发/演示 | 高(不可追踪) |
镜像校验与一致性的关系
好,现在我们把视角拉回这门课的主题。
Docker 镜像校验收官是为了回答一个问题:“你正在运行的容器,真的是由你预期的那个镜像构建的吗?”
你可能会想:“这不废话嘛,我 pull 了 nginx:1.25,那容器就是 nginx:1.25 啊。” 不一定。镜像标签可以被覆盖,镜像内容可以被篡改,构建过程可能被打断。这些问题我都在生产环境里见过。
所以,我们需要一套方法——从镜像的 Digest(内容哈希)、元数据、层信息等多个维度,来校验镜像与容器是否真的“一致”。这就是整个 30 章课程要解决的问题。
核心结论: 容器一致性 = 镜像完整性 + 运行时配置可信。镜像校验是容器一致性的前提。
知识图谱
下面这张图概括了本章的核心逻辑:Docker 镜像的构成与生命周期,以及它如何导向后续的校验与一致性保障。
图里能看到,镜像可以通过多种方式进入本地(构建、拉取、导入、commit),然后被用来创建容器。我们后续的校验工作,就是在这些“输入”和“输出”环节,验证镜像的完整性。
本章小结
到这,我们已经搭好了基础框架:
- 镜像是什么,它和虚拟机的区别。
- 镜像分层和元数据的概念。
- 镜像从构建到删除的完整生命周期。
- 镜像仓库和标签管理的重要性。