Docker镜像原理
1.镜像是什么
Docker镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件。
镜像中包含运行某个软件所需的所有内容,例如:
- 代码
- 运行时库
- 环境变量
- 配置文件
应用可以直接打包成Docker镜像,然后通过镜像启动容器运行。
获取镜像的常见方式:
- 从远程仓库下载。
- 由别人拷贝提供。
- 通过Dockerfile自己制作镜像。
2.Docker镜像加载原理
2.1UnionFS联合文件系统
UnionFS(联合文件系统)是一种分层、轻量级并且高性能的文件系统。它支持把文件系统的修改作为一次提交,一层层叠加起来,同时也可以把不同目录挂载到同一个虚拟文件系统下。
UnionFS是Docker镜像的基础。镜像可以通过分层进行继承,基于基础镜像可以制作出各种具体的应用镜像。
UnionFS的特点:
- 一次可以同时加载多个文件系统。
- 从外部看,只能看到一个统一的文件系统。
- 联合加载会把各层文件系统叠加起来,最终展示出包含所有底层文件和目录的结果。
2.2bootfs和rootfs
Docker镜像实际上由一层一层的文件系统组成,这种层级文件系统就是UnionFS。
bootfs主要包含bootloader和kernel:
bootloader主要用于引导加载kernel。- Linux刚启动时会加载
bootfs文件系统。 - Docker镜像最底层是
bootfs。 - 当
boot加载完成后,整个内核会进入内存,此时内存使用权由bootfs转交给内核,系统会卸载bootfs。
rootfs位于bootfs之上:
rootfs包含典型Linux系统中的/dev、/proc、/bin、/etc等标准目录和文件。rootfs对应不同操作系统发行版,例如Ubuntu、CentOS等。

平时安装到虚拟机里的Ubuntu通常有好几个G,为什么Docker镜像可以只有几十MB?

原因:对于一个精简的OS,rootfs可以很小,只需要包含最基本的命令、工具和程序库即可。因为底层直接使用宿主机的kernel,镜像自身只需要提供rootfs。
所以不同Linux发行版的bootfs基本一致,rootfs会有差别。不同发行版可以共用bootfs。
对比结果:虚拟机启动通常是分钟级,容器启动通常是秒级。
3.Docker镜像分层机制
3.1分层下载
下载镜像时,可以观察日志输出,镜像是一层一层下载的。

Docker镜像采用分层结构的好处:
- 多个镜像如果都基于相同的Base镜像构建,宿主机磁盘上只需要保留一份Base镜像。
- 内存中也只需要加载一份Base镜像,就可以为多个容器服务。
- 镜像的每一层都可以被共享。
3.2查看镜像分层
可以通过docker image inspect命令查看镜像分层信息。
docker image inspect tomcat示例输出节选:
ubuntu@Mystpet:~$ docker image inspect tomcat
[
{
"Id": "sha256:28cba8cc937ca4db18cd32d559f49708fb2868c79c3441d793be0611d2bd7d56",
"RepoTags": [
"tomcat:latest"
],
"RepoDigests": [
"tomcat@sha256:28cba8cc937ca4db18cd32d559f49708fb2868c79c3441d793be0611d2bd7d56"
],
"Comment": "buildkit.dockerfile.v0",
"Created": "2026-03-17T02:50:37.478195863Z",
"Config": {
"ExposedPorts": {
"8080/tcp": {}
},
"Env": [
"PATH=/usr/local/tomcat/bin:/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"JAVA_HOME=/opt/java/openjdk",
"LANG=en_US.UTF-8",
"LANGUAGE=en_US:en",
"LC_ALL=en_US.UTF-8",
"JAVA_VERSION=jdk-25.0.2+10",
"CATALINA_HOME=/usr/local/tomcat",
"TOMCAT_NATIVE_LIBDIR=/usr/local/tomcat/native-jni-lib",
"LD_LIBRARY_PATH=/usr/local/tomcat/native-jni-lib",
"TOMCAT_MAJOR=11",
"TOMCAT_VERSION=11.0.18",
"TOMCAT_SHA512=e428203454e57962296e6e95705e46a1406d15569f67ea0cbd417f38fcad85e81de6fa1be62cfa660ec746312aefb87c39127eef7348e6f78cb57e9afb862ed4"
],
"Cmd": [
"catalina.sh",
"run"
],
"WorkingDir": "/usr/local/tomcat",
"Labels": {
"org.opencontainers.image.ref.name": "ubuntu",
"org.opencontainers.image.version": "24.04"
}
},
"Architecture": "amd64",
"Os": "linux",
"Size": 155554281,
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:f2a7f072635332d307212e318e07284948b89f4167fce5c4d7c9cfb7590b74b6",
"sha256:c19a303f70f0750fa67953740982715fa23cd40108f673526753aec8b938e8c3",
"sha256:03687485058608317706c1b0b0f84960a876c296d12e4a0260853340ece802b9",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:b51be15d613f35209c07bb11d70fc2af5fb2b8de4269d9c9d54865f86f2d8610",
"sha256:d726f2064a44be786bd1c51efe697f5c9d7c9dfc04f77c86f0931cd953137df8",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef",
"sha256:48806314f082ee75f7267c110e2f9798268a3049e89ecfb59d431925dae22cf4",
"sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
]
}
}
]重点看RootFS中的Layers字段,它记录了镜像的分层信息。
3.3分层构建过程
所有Docker镜像都起始于一个基础镜像层。当进行修改或者增加新内容时,就会在当前镜像层之上创建新的镜像层。
示例:
1.基于Ubuntu Linux16.04创建一个新镜像,这是第一层。
2.在镜像中添加Python包,会在基础镜像层之上创建第二层。
3.继续添加一个安全补丁,会创建第三层。
最终镜像包含这3个镜像层。

镜像始终是当前所有镜像层的组合。下面例子中,每个镜像层包含3个文件,而镜像最终包含来自两个镜像层的6个文件。

下面是一个稍微复杂的三层镜像。对外看来整个镜像只有6个文件,因为最上层中的文件7是文件5的更新版本。

这种情况下,上层镜像层中的文件会覆盖底层镜像层中的文件。文件的更新版本会作为一个新镜像层添加到镜像中。
Docker通过存储引擎实现镜像层堆栈,并保证多个镜像层对外展示为统一的文件系统。
Linux上常见的存储引擎包括:
- AUFS
- Overlay2
- Device Mapper
- Btrfs
- ZFS
每种存储引擎都基于Linux中对应的文件系统或者块设备技术,并且各自有不同的性能特点。
Docker在Windows上仅支持windowsfilter一种存储引擎,该引擎基于NTFS文件系统实现分层和CoW。
下图展示了三层镜像合并后的统一视图。所有镜像层合并后,对外提供统一的文件系统视图。

4.镜像层和容器层
Docker镜像都是只读的。容器启动时,会在镜像顶部加载一个新的可写层。
这个新的可写层就是容器层,容器层下面的都叫镜像层。

简单理解:
- 镜像层:只读,用来提供基础文件和运行环境。
- 容器层:可写,用来保存容器运行时产生的修改。
5.commit镜像
docker commit可以把当前容器提交成一个新的镜像副本。
命令格式:
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[版本TAG]示例:
ubuntu@Mystpet:~$ docker commit -a="mystpet" -m="test" 1b5 tomcat01:1.0说明:如果想保存当前容器的状态,可以通过docker commit提交生成一个新镜像。它的效果类似于给虚拟机创建快照。