在 Docker 中,镜像是一个包含了运行应用程序所需的所有代码、运行时环境、库、环境变量和配置文件的不可变模板。它是 Docker 容器的基础,容器则是镜像的运行实例。
简单来说,镜像可以理解为:
- 一个 "快照" 或 "模板",包含了应用及其依赖的完整文件系统
- 只读的静态文件,一旦创建就无法修改
- 可以被用来创建多个相同的容器实例
1.UnionFS(联合文件系统)
UnionFS(联合文件系统)是一种特殊的文件系统,它能够将多个独立的文件系统(目录)以透明的方式合并成一个单一的虚拟文件系统。这种技术的核心是 "联合挂载"(Union Mount),让用户看起来只有一个统一的文件系统,而实际数据可能来自多个不同的物理位置。
UnionFS 的核心特性:
-
分层合并可以将多个目录(称为 "层")按顺序叠加,形成一个统一视图。当访问文件时,系统会从顶层开始查找,找到后就返回该文件,底层的同名文件会被 "隐藏"(而非被覆盖)。
-
**写时复制(Copy-on-Write)**对于只读的底层(如 Docker 镜像层),当需要修改其中的文件时,系统会先将文件复制到可写层再进行修改,避免直接改动底层数据。这保证了底层的只读性和安全性,同时实现了高效的资源复用。
-
空间高效多个层可以共享相同的数据,无需重复存储,大大节省了存储空间。例如,多个 Docker 容器可以共享同一个基础镜像层,只在各自的可写层保存差异化数据。
也就是将多个不同位置的文件统一起来使用,可以达到文件的复用能力,同时在修改文件时采用复制的方式保证安全
对于分层这里举一个例子,有tomcat和mysql,tomcat和mysql都运行在linux系统上,那么linux就在tomcat和mysql的下层,当访问tomcat和mysql时,会同时往下层找到其依赖的所有文件形成一个统一完整的文件,这里tomcat和mysql访问的是同一个linux,修改时会通过复制的方式,将文件复制独属于自己的一份来进行修改。
2. 镜像加载原理
Docker 镜像的加载原理基于联合文件系统(UnionFS) 和分层叠存储(Layered Storage) 机制,核心是将多个只读镜像层通过联合挂载技术合并为一个统一的文件系统视图,同时在运行容器时添加可写层以处理动态修改。
具体加载过程可以分为以下几个关键步骤:
-
镜像的分层存储结构
Docker 镜像由多个只读层(Layer)组成。例如:
- bootfs 最为最底层
- rootfs,在bootfs之上,包含Linux系统中的 /dev,/proc,/bin等标准目录和文件
- 上层依次叠加应用依赖层、代码层、配置层等
- 每层仅存储与前一层的差异数据,相同内容会被复用
-
联合文件系统的合并挂载
当加载镜像时,Docker 使用 UnionFS(将所有只读层按顺序 "堆叠" 并合并:
- 从最上层开始查找文件,若找到则直接使用,底层同名文件会被 "隐藏"
- 用户看到的是一个完整、统一的文件系统视图,无需关心实际分层
-
容器启动时的可写层镜像本身是只读的,当通过镜像创建容器时:
- Docker 会在镜像层之上添加一个可写层(容器层)
- 容器内的所有修改(如新建 / 删除文件、修改配置)都仅发生在可写层
- 若修改底层只读文件,会触发写时复制(Copy-on-Write):先将文件从只读层复制到可写层,再修改可写层的副本
-
高效的存储与复用
- 多个容器可共享同一镜像的只读层,仅需为每个容器维护独立的可写层,极大节省存储空间
- 镜像层一旦创建不可修改,保证了环境一致性和安全性
- 拉取镜像时,仅需下载本地缺失的层,提高传输效率
3. commit命令
commit命令可以把我们修改过的容器作为一个镜像提交到我们本地,下次可以直接使用:
bash
docker commit -a="提交者" -m="描述" 容器id 镜像名称
我这里运行了一个tomcat容器:

可以看到webapps中没有web应用,那么我就可以把我的web应用添加到webapps中通过commit提交下次就可以直接使用: