• 由于docker的分层存储,被删除的文件一直存在于分层架构中,只是被标记为删除罢了
  • 可以使用docker history [img_name]指令来看目标镜像的分层架构
  • 使用docker images [img_name]查看镜像大小
  • 解决方式是使用export/import来重构文件分层
  • 重构文件系统会丢失cmd/端口/等元信息
  1. 首先准备测试用的dockerfile

    # docker build -t t1 .
    
    FROM ubuntu
    # 快速安装,无人值守模式
    ENV DEBIAN_FRONTEND=noninteractive
    # 申请端口
    EXPOSE 22
    
    
    # 运行安装脚本
    # RUN bash /tmp/run.sh
    RUN dd if=/dev/zero of=100M.bin count=1 bs=100MB
    RUN dd if=/dev/zero of=10M.bin count=1 bs=10MB
    RUN rm 100M.bin
    
    CMD ["bash"]
    • 这里使用docker build -t t1 .指令构建为镜像t1
  2. 体积计算:

    1. 假设:已知ubuntu的初始大小为72.8MB
    2. 那么这个image理论的大小应该是72.8+100+10-100=82.8MB
    3. 可实际上却是72.8+100+10=182.8M

      # docker images t1
      REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
      t1           latest    7dc3c4768c6e   2 minutes ago   183MB
    4. 再看来一下文件分层

      # docker history t1
      │IMAGE          CREATED         CREATED BY                                      SIZE      COMM
      │ENT
      │7dc3c4768c6e   3 minutes ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
      │f7977abaef92   3 minutes ago   /bin/sh -c rm 100M.bin                          0B
      │847d68ab1484   3 minutes ago   /bin/sh -c dd if=/dev/zero of=10M.bin count=…   10MB
      │62baa88f2d83   3 minutes ago   /bin/sh -c dd if=/dev/zero of=100M.bin count…   100MB
      │2bbf0d43850b   3 minutes ago   /bin/sh -c #(nop)  EXPOSE 22                    0B
      │a6e876477399   3 minutes ago   /bin/sh -c #(nop)  ENV DEBIAN_FRONTEND=nonin…   0B
      │ba6acccedd29   2 months ago    /bin/sh -c #(nop)  CMD ["bash"]                 0B
      │<missing>      2 months ago    /bin/sh -c #(nop) ADD file:5d68d27cc15a80653…   72.8MB
      
      • 可以发现rm 100M.bin并没有真正的删除文件
  3. 真正的解决办法是先初始化为实例,然后直接重新导出导入.这样才能重构文件分层

    # 重构文件分层
    function mini_images()
    {
        # 原始镜像名称
        src=$1
        
        # 临时容器名称,不要和已有容器冲突
        dk_tmp=cv.by.kms.app
        
        # 首先实例化容器
        docker create -it -P --name $dk_tmp $src
        
        # 接着导出容器
        docker export $dk_tmp -o $dk_tmp.tar
        # docker export $dk_tmp |gzip > $dk_tmp.tar.gz
        
        # 删除原始镜像以及临时容器
        docker rm $dk_tmp
        docker rmi $src
        # 重新导入
        docker import $dk_tmp.tar $src
        rm $dk_tmp.tar
        # show一下结果
        docker images $src
    }
    
    # 参数: 原始镜像名称(希望重构的镜像)
    mini_images t1
    • 重构之后再使用docker images t1可以发现体积如愿的缩小到82.8MB

      # docker images t1
      REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
      t1           latest    3f18764312ee   58 seconds ago   82.8MB
  4. 重构文件系统会丢失cmd等信息,需要配合dockerfile重新构建.只适合作为基础镜像
  5. 可以使用inspect+jq的方式来查看原始镜像/容器的启动信息

    docker inspect t1|jq .[0]|jq .Config.Cmd 
    docker inspect t1|jq .[0]|jq .Config.Entrypoint 
Last modification:January 7, 2022
如果觉得我的文章对你有用,请随意赞赏