被删除的文件还占着镜像空间,怎么把它们真正去掉?这篇对比分两层删除、同一层删除、多阶段压平、export | import 和已被移除的 --squash,量出大小和层数,并看压平会丢掉什么。
镜像 Size=76.5 MB,RootFS 层数=4,Cmd=['echo', 'from-cmd'],Env 有 DEMO 吗=True docker history 里各层的大小:4.1kB | 31.5MB | 4.1kB | 0B | 0B 容器里 /big.bin 存在吗?ls: /big.bin: No such file or directory
后一层的删除只是在新层里标记文件被删,前一层里的内容原样保留(c3、c21)。所以镜像里装完东西再清理缓存,必须和安装放在同一条 RUN 里。
镜像 Size=13.6 MB,RootFS 层数=3,Cmd=['echo', 'from-cmd'],Env 有 DEMO 吗=True
同一条 RUN 产生一个层,文件在这层里创建后又删除,最终层里没有它,体积和空 alpine 一样。
FROM scratch + COPY --from=<A> / /:镜像 Size=13.6 MB,RootFS 层数=1,Cmd=None,Env 有 DEMO 吗=False 运行它:squashed-ok 再补上 ENV 和 CMD:镜像 Size=13.6 MB,RootFS 层数=1,Cmd=['echo', 'from-cmd'],Env 有 DEMO 吗=True
多阶段构建 FROM scratch 再 COPY --from=… / / 得到单层镜像;ENV、CMD 这些元数据不会带过来(我测了这两项),要重新写。压成一层的代价是失去层复用(c18),我没有量化这一点。
镜像 Size=13.6 MB,RootFS 层数=1,Cmd=None,Env 有 DEMO 吗=False
docker export | docker import 同样压成 1 层,同样丢掉 Cmd 和 Env。
docker build --squash:退出码 0;['WARNING: experimental flag squash is removed with BuildKit. You should squash inside build using a multi-stage Dockerfile for efficiency.'] 加了 --squash 之后的镜像:镜像 Size=76.5 MB,RootFS 层数=4,Cmd=['echo', 'from-cmd'],Env 有 DEMO 吗=True(没有被压成 1 层)
在这个 Docker 的 BuildKit 构建器下,--squash 被忽略,只打一条警告;经典构建器下的行为我没有测。