1. Docker 简介与核心概念归纳总结

说实话,我刚接触 Docker 那会儿,只觉得它是个“轻量级虚拟机”。后来踩了好几次坑才发现——它的核心价值根本不在虚拟化,而在环境一致性。什么叫环境一致性?你写代码的机器、测试的服务器、线上生产环境,全部用同一套软件栈运行同一个应用,不会出现“本地跑得好好的,部署就崩了”这种问题。

我习惯把 Docker 看作一个运输集装箱。想象一下:你装满货物(应用+依赖)的箱子,无论是放在货轮、火车还是卡车上,只要集装箱本身结构不变,里面的货物就不会受外界影响。Docker 做的事情与此类似——把你的应用和它所依赖的操作系统库、配置文件、运行时环境打包成一个标准化的“容器”,在任何地方都能以完全相同的方式运行。

1.1 镜像与容器:到底有什么区别?

很多初学者会把镜像和容器搞混。我当年也一样。其实很简单:镜像是只读的模板,容器是运行中的实例。

你想想看,面向对象编程里,类 和 对象 的关系是什么?类定义属性和方法,对象才是真正占用内存的那个实体。镜像就是那个“类”,容器就是那个“对象”。

我建议你记住下面这张对比表,遇到面试或日常交流时直接套用:

维度 镜像 (Image) 容器 (Container)
可写性 只读,不可修改 可读写,运行时会生成可写层
生命周期 静止,一旦构建就固定 动态,可以启动、停止、删除
存储位置 本地或镜像仓库 仅存在于当前 Docker 主机
共享 通过 Docker Hub / 私有仓库分发 不能直接共享,但可以提交为新镜像
类比 ISO 安装盘 运行中的虚拟机

重要警告:容器停止后,它的可写层默认会被保留。如果你频繁创建和删除容器,磁盘上的“悬空镜像”和“退出容器”会慢慢堆积。我曾经在一个 CI 服务器上没清理,三个月后居然占掉了 80 GB!建议定期执行 docker system prune -f 清理无用资源。

1.2 镜像分层:Docker 为什么这么快?

你可能会问:一个 Ubuntu 基础镜像 + Python 运行环境 + 自己的代码,加起来几百 MB,怎么做到秒级部署?答案藏在联合文件系统(UnionFS)里。

Docker 镜像由一层层只读文件系统叠加而成。每一层对应 Dockerfile 中的一条指令。比如:

FROM ubuntu:22.04
RUN apt-get update && apt-get install -y python3
COPY ./app.py /app/
CMD ["python3", "/app/app.py"]

这个 Dockerfile 产生了 4 个镜像层:基础层、软件安装层、文件拷贝层、元数据层。启动容器时,Docker 在最上面再加一个可写层(容器层的读写修改都写在这里)。

为什么快?因为层可以共享。假如你在一台机器上跑 10 个 Python 应用,它们都基于同一个 ubuntu:22.04 + python3 层组合。那么这前两层只存储一份,容器只多一层(你的代码)。磁盘利用率和启动速度都大幅提升。

我记得有一次帮团队优化部署流程,原本每个服务都要完整拉取整个镜像。改用基于同一个基础 layer 的多阶段构建后,部署速度从 3 分钟降到了 30 秒。

1.3 仓库:镜像的中转站

镜像需要分发才能在不同机器上使用。Docker Registry(仓库)就是存放和分发镜像的服务器。默认的是 Docker Hub,但生产环境里我一般用自建的 Harbor 或者 AWS ECR。

拉取镜像的命令非常直接:

docker pull ubuntu:22.04

你也可以打标签(tag)后推送:

docker tag myapp:latest myregistry.com/myapp:v1
docker push myregistry.com/myapp:v1

有个细节容易被忽略:镜像的 Digest(摘要值)才是真正唯一的标识。标签可以变,但 digest 不变。我在做 CI/CD 流水线时,会强制使用 digest 而不是标签来引用镜像,避免因为标签被覆写而产生不一致。

个人习惯:每次构建镜像后,除了打语义标签(如 v1.2),我还会把 digest 记录到部署配置的注释里。这样回溯问题时,能准确知道到底是哪个镜像被部署过。

1.4 环境一致性的底层支柱:命名空间与 Cgroups

Docker 不是真的“隔离操作系统”,它是通过 Linux 内核特性实现的进程级隔离:

  • 命名空间(Namespace):让容器里的进程只能看到属于该容器的进程、网络、文件系统等。例如 PID Namespace 让容器以为自己是 1 号进程。
  • 控制组(Cgroups):限制容器使用的 CPU、内存、磁盘 IO,防止某个容器把宿主机资源吃光。

说白了,容器只是宿主机上的一个特殊进程,只不过它被“蒙在鼓里”——以为自己是一台独立的机器。这就是环境一致性背后的机制:无论你在哪个宿主机上启动同一个镜像,它所处的“假环境”是完全一样的。

1.5 本章知识体系图

下面这张 SVG 展示了 Docker 核心概念之间的关系,我把它放在这里当作本章的“脑图”。你可以看到:镜像通过 Dockerfile 构建,从仓库拉取,由 Docker 引擎创建为容器,容器之间互不干扰,底层依赖 Linux 内核的命名空间和 Cgroups。

Docker 核心概念关系图 Dockerfile 镜像 (Image) 仓库 (Registry) 容器 (Container) 命名空间 Cgroups Docker 引擎 push / pull docker run ❶ 镜像由 Dockerfile 构建,可 push 到仓库 ❷ 容器从镜像启动,由 Docker 引擎管理 ❸ 底层依赖 Linux 命名空间与 Cgroups

1.6 本章核心知识点归纳

为了便于你后续查阅,我把本章的关键内容浓缩成了一张清单。每一条都是在你实际工作中会反复用到的:

  • 镜像:只读模板,分层存储,可通过 Dockerfile 构建。
  • 容器:镜像的运行实例,额外有一个可写层,隔离性来自命名空间。
  • 仓库:镜像的存储与分发中心,支持 tag 和 digest。
  • Dockerfile 指令:FROM, RUN, COPY, CMD, ENTRYPOINT 等,每一条创建一个镜像层。
  • 环境一致性:同一镜像在任何 Docker 主机上启动的容器,内部环境都相同。
  • 清理策略:定期执行 docker system prune 和 docker image prune,避免磁盘爆满。

一句话总结:Docker 通过“镜像-容器-仓库”三件套,结合命名空间与 Cgroups,实现了前所未有的环境一致性。你只需关心应用的构建与打包,运行环境交给 Docker 来保证。