You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于大Docker基础镜像生成更小镜像的可行性及问题咨询

为什么删除Docker镜像里的包后体积没变化?怎么缩小镜像?

这问题我太懂了!很多人第一次折腾Docker都会踩这个坑——明明在构建时删了好大一堆包,结果镜像体积纹丝不动,核心原因就是Docker的分层存储机制

先搞懂为啥删了文件体积不变

Docker镜像是由一层层只读的镜像层叠加出来的,每一条RUN命令都会生成一个新的镜像层。你用apt remove或者rm删文件的时候,其实只是在新的层里给这些文件打了个“已删除”的标记,但原来的基础镜像层里的文件还完完整整地存在着。镜像的总大小是所有层的大小加起来,所以哪怕你删了20MB的内容,原来100MB的基础层还在,总大小自然没变化。

可行的缩小镜像方法

针对你这种可选基础镜像都是大体积通用镜像的场景,这两个方法最实用:

  • 把安装和清理命令合并到同一个RUN层
    绝对不要把安装和清理分成两条RUN命令,比如这种错误示范:

    RUN apt-get update && apt-get install -y heavy-package
    RUN apt-get remove -y heavy-package && apt-get clean
    

    正确的做法是把所有相关操作塞进同一条RUN,这样所有操作都在同一个镜像层里完成,清理后的状态会被直接打包,不会留下之前安装包的痕迹:

    RUN apt-get update && \
        apt-get install -y heavy-package && \
        # 这里放你需要用这个包完成的操作,比如编译、处理文件等
        apt-get remove -y heavy-package && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/*
    
  • 用多阶段构建彻底剥离冗余
    这是我最推荐的方案,尤其适合需要先安装依赖做构建,再只保留最终产物的场景。比如:

    # 第一阶段:用大基础镜像做构建工作,这个阶段的层不会进最终镜像
    FROM big-base-image as builder
    RUN apt-get update && apt-get install -y build-essential some-tools
    COPY ./source-code /app
    RUN cd /app && make build # 假设这是生成最终产物的命令
    
    # 第二阶段:只从builder阶段复制需要的产物,基础镜像还是你只能用的那个大镜像
    FROM big-base-image
    COPY --from=builder /app/final-product /usr/local/bin/
    # 现在最终镜像里只有基础镜像+这个产物层,builder阶段的所有冗余都被抛弃了
    
  • 别忘了清理各种缓存文件
    除了包管理的清理,还要顺手删掉系统里的临时文件,比如:

    • rm -rf /var/lib/apt/lists/*(apt的下载缓存)
    • rm -rf /tmp/* /var/tmp/*(系统临时目录)
    • 如果用yum的话,加上yum clean all && rm -rf /var/cache/yum

按照这些方法操作,你肯定能把基于大基础镜像的新镜像体积压到最小,甚至可能比你预期的还小!

内容的提问来源于stack exchange,提问作者Prakash

火山引擎 最新活动