🐳 Docker 镜像瘦身的起点:用 docker history 揭秘其“族谱”
明明只是部署了一个轻量级应用,但查看镜像大小时却发现它轻松超过了1GB。你可能会感到困惑,心想“我到底加了什么东西?”。这时,我们需要做的就是揭开镜像的“族谱”,一探究竟。

“你到底吃了什么,怎么长这么大了?”
Docker 镜像就像层层堆叠的洋葱皮(层)。docker history 命令就像一台X光机,能一层层剥开这些“外衣”,找出导致镜像臃肿的“元凶”。
其基本用法非常简单:
# 基本用法
docker history [选项] <镜像名称:标签>
# 示例:查看我的应用历史
docker history my-app:latest
执行该命令后,会从最新层开始,逆序显示镜像的所有层,直至基础镜像。
IMAGE CREATED CREATED BY SIZE
a6215f271958 5 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:f28242cf608f6... 7.81MB
请仔细观察 SIZE 这一项。如果本应是 0B 的地方却显示了几百MB,那么它就是需要“瘦身”的对象。凭经验来看,总会有一些地方“不对劲”。
💡 实用技巧:
--no-trunc默认情况下,如果命令过长,输出内容会被截断。此时,加上
--no-trunc选项,就能完整显示所有命令,这对于精确分析至关重要。
docker history --no-trunc my-app:latest
实战案例:“罪魁祸首是 chown”
我来分享一个亲身经历的真实案例。我构建了一个 150MB 的项目文件,但镜像大小却诡异地超过了 300MB。而“罪魁祸首”就是 Dockerfile 中看似再普通不过的两行命令。
[低效方法:创建两个层]
# 1. 首先复制文件(默认以 root 用户复制)
COPY . .
# 2. 为安全起见更改所有权(作为单独命令执行)
RUN chown -R appuser:appgroup /app
构建之后,用 docker history 查看,结果如下:
IMAGE CREATED BY SIZE
<layer_id_2> /bin/sh -c chown -R appuser:appgroup /app 150MB <-- (问题所在!)
<layer_id_1> /bin/sh -c #(nop) COPY dir:abc in /app 150MB
Docker 层级的“可怕”之处就在这里。第一步复制 150MB 文件时,会创建一个层。但第二步执行 chown 命令时,Docker 会认为“咦?文件信息(所有权)变了?那我就把更改后的状态再创建一个新层!”它会将原有的 150MB 文件原封不动地复制一份,再堆叠一个新层。
结果,内容完全相同,只是所有权不同的文件却被双重存储,导致镜像大小翻倍。
解决方案:一行命令搞定瘦身!
解决方案很简单。只需在复制文件时直接指定所有权,就能将多个层合并为一个。
[高效方法:创建单个层]
# 复制文件时同时指定所有权!
COPY --chown=appuser:appgroup . .
将 Dockerfile 这样修改后,再次执行 docker history,结果会发生翻天覆地的变化。
IMAGE CREATED BY SIZE
<layer_id_1> /bin/sh -c #(nop) COPY --chown=appuser... dir:abc 150MB
看到了吗?只创建了一个层,镜像大小又“苗条”地回到了 150MB。仅仅是将两条命令合并为一行,镜像容量就减少了一半。
结论:构建后务必检查“历史记录”!
请记住,Docker 镜像的特点是每条命令对应一个层。
就像编写代码后进行测试一样,在构建镜像后,也请养成习惯性地运行 docker history --no-trunc 命令。当“这个 apt-get 为什么这么大?”、“为什么要特意将这个层分开?”之类的疑问接踵而至时,不知不觉中,您就会构建出非常轻量且高效的系统。
因为不必要的层是系统的敌人!
这篇文章对您有帮助吗? 如果有,请点赞!
也请阅读相关文章。
相关文章