1. 概述
随着越来越多的应用通过 Docker 进行部署,了解其生态系统的基本原理变得尤为重要。虽然现有的工具让打包和部署变得简单,但在某些时候,我们可能需要排查部署中的一些问题。
其中,镜像对比是调试部署时常见的任务之一。本文将介绍 Docker 镜像的结构,并演示如何查看两个镜像之间的差异。
2. Docker 镜像简介
Docker 镜像是构建容器的蓝图,我们可以将其理解为运行一个应用所需的所有文件和目录的集合,包括操作系统、第三方依赖库以及我们自己的代码。
底层来看,这些镜像本质上就是 tar 文件。构建镜像时,会生成多个层级(layer),每一层都包含一组文件和目录。
通常我们会基于一个已有镜像进行扩展。例如构建一个 Spring Boot 应用,我们可能会基于 OpenJDK 镜像,然后添加自己的 Java 文件(如 fat jar)和依赖库。
最终,所有层级被打包成一个完整的镜像,包含运行应用所需的一切。
3. 查看单个 Docker 镜像
我们可以通过以下命令列出本地镜像:
$ docker image ls
spring-petclinic 2.7.0-SNAPSHOT 0f9d2d05687b 2 months ago 266MB
spring-petclinic 2.6.0-SNAPSHOT 1d79d5bd7779 3 months ago 265MB
然后使用 docker inspect
命令查看某个镜像的详细信息:
$ docker inspect 0f9d2d05687b
[
{
"Id": "sha256:0f9d2d05687b8c816cbf54f63cf7e5aa7144d28e1996d468bfaf555a3882610a",
"RepoTags": [
"spring-petclinic:2.7.0-SNAPSHOT"
],
"Architecture": "amd64",
"Os": "linux",
"Size": 266141567,
"VirtualSize": 266141567,
...
}
]
该命令展示了镜像的元信息,如创建时间、层级结构等,但不会展示镜像内部的具体内容。
要查看内容,可以先将镜像保存为 tar 文件:
$ docker save 0f9d2d05687b > 0f9d2d05687b.tar
再使用 tar 命令查看:
$ tar tvf 0f9d2d05687b.tar
drwxr-xr-x 0 0 0 0 Dec 31 1979 02805fa4a4f35efdcf3804bc1218af1bc22d28ee521cc944cab5cac5dbe5abfe/
-rw-r--r-- 0 0 0 3 Dec 31 1979 02805fa4a4f35efdcf3804bc1218af1bc22d28ee521cc944cab5cac5dbe5abfe/VERSION
-rw-r--r-- 0 0 0 477 Dec 31 1979 02805fa4a4f35efdcf3804bc1218af1bc22d28ee521cc944cab5cac5dbe5abfe/json
-rw-r--r-- 0 0 0 1024 Dec 31 1979 02805fa4a4f35efdcf3804bc1218af1bc22d28ee521cc944cab5cac5dbe5abfe/layer.tar
...
tar 命令可以列出镜像中的文件结构,也可以提取特定文件用于分析。
4. 对比两个 Docker 镜像
前面我们了解了如何查看单个镜像的内容。接下来,我们看看如何对比两个镜像之间的差异。
根据我们要比较的内容,可以选择不同的工具:
4.1. container-diff
Google 的 container-diff 是一个专门用于对比镜像的工具,支持多种对比方式(如文件、RPM 包、APT 包等)。
示例命令如下:
$ /usr/local/bin/container-diff diff \
daemon://spring-petclinic:2.6.0-SNAPSHOT \
daemon://spring-petclinic:2.7.0-SNAPSHOT \
--type=file
输出内容分为三部分:
✅ 新增文件(Added):
/workspace/BOOT-INF/lib/byte-buddy-1.12.10.jar 3.7M
/workspace/BOOT-INF/lib/classgraph-4.8.139.jar 551.7K
/workspace/BOOT-INF/lib/ehcache-3.10.0.jar 1.7M
/workspace/BOOT-INF/lib/h2-2.1.212.jar 2.4M
/workspace/BOOT-INF/lib/hibernate-core-5.6.9.Final.jar 7.1M
/workspace/BOOT-INF/lib/jackson-annotations-2.13.3.jar 73.9K
❌ 删除文件(Deleted):
These entries have been deleted from spring-petclinic:2.6.0-SNAPSHOT:
FILE SIZE
/workspace/BOOT-INF/lib/byte-buddy-1.11.22.jar 3.5M
/workspace/BOOT-INF/lib/classgraph-4.8.115.jar 525.4K
/workspace/BOOT-INF/lib/ehcache-3.9.9.jar 1.7M
/workspace/BOOT-INF/lib/h2-1.4.200.jar 2.2M
/workspace/BOOT-INF/lib/hibernate-core-5.6.7.Final.jar 7.1M
/workspace/BOOT-INF/lib/jackson-annotations-2.13.2.jar 73.9K
⚠️ 修改文件(Changed):
These entries have been changed between spring-petclinic:2.6.0-SNAPSHOT and spring-petclinic:2.7.0-SNAPSHOT:
FILE SIZE1 SIZE2
/layers/config/metadata.toml 16.6K 1.9K
/workspace/META-INF/maven/org.springframework.samples/spring-petclinic/pom.xml 13.3K 13.3K
/workspace/BOOT-INF/classes/org/springframework/samples/petclinic/owner/OwnerController.class 7.8K 7.7K
/workspace/org/springframework/boot/loader/ExecutableArchiveLauncher.class 6.6K 7.5K
...
container-diff 的输出非常清晰,能快速定位到依赖变化和具体代码修改。
4.2. dive
dive 是另一个强大的开源镜像分析工具,它能逐层解析镜像并以文件树的形式展示。
查看单个镜像的结构如下图所示:
虽然 dive 没有原生支持镜像对比功能,但我们可以在两个终端中分别运行 dive 并手动对比,如下图:
这样可以直观看到哪些层级是相同的,哪些是不同的,适合快速分析镜像构建过程中的变化。
5. 总结
本文介绍了 Docker 镜像的结构,并演示了如何查看和对比镜像内容。
- ✅
docker inspect
和docker save
可用于查看单个镜像的结构和文件; - ✅ 若需对比两个镜像,可使用第三方工具:
- container-diff:专为镜像对比设计,支持文件、包等多维度对比;
- dive:适合逐层查看镜像内容,也可通过双窗口方式手动对比差异。
选择合适的工具能大大提升排查镜像问题的效率,避免踩坑。