• 镜像瘦身:每一层都不能放过


    网上很多人都说镜像瘦身需要把所有命令放在一条来执行,这没有错,但只是问题表象,没有触及本质。
    当我打了一个带源码编译的镜像,结果异常庞大,明明已经删了源码包,为什么还那么大呢?当我想尝试放在一条命令时,简洁理论告诉我这非常不美观,我每个RUN都是一个不同的软件,放在一起不是很混乱吗?可读性变差了,所以一定不是这样的。

    镜像瘦身

    下面的镜像是为了升级centos7里面的openssl版本为1.1.1,从源码构建。
    Dockerfile如下:

    ARG BASE_IMAGE=centos:7.6.1810
    FROM $BASE_IMAGE
    
    ENV  TZ           Asia/Shanghai
    
    RUN yum install -y gcc gcc-c++ vim kde-l10n-Chinese bison gettext texinfo make autotool automake \
            wget curl zip unzip bzip2 file sudo readline ncurses which \
            git net-tools man-db man-pages-zh-CN wqy-microhei-fonts bash-completion \
            man-pages && yum clean all && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
    
    ADD  packages.tar    /home/
    WORKDIR /home/packages
    
    RUN tar -xf make-4.2.1.tar.gz && cd make-4.2.1 && mkdir build && cd build && ../configure --prefix=/usr && make && make install
    
    # 安装openssl1.1.1
    RUN tar -xzvf openssl-1.1.1q.tar.gz && cd openssl-1.1.1q \
        && ./config shared --openssldir=/usr/local/openssl --prefix=/usr/local/openssl \
        && make && make install \
        && echo "/usr/local/openssl/lib/" >> /etc/ld.so.conf \
        && ldconfig
    
    WORKDIR /
    RUN rm -rf /home/packages && rm -rf /var/cache/yum/* && rm -rf /var/lib/rpm/__db.* && yum clean all && rm -rf /var/lib/yum/*
    
    WORKDIR /home/finance
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    瘦身之前

    结果镜像大小:810MB,分层查看openssl这一层145MB

    $ docker images
    REPOSITORY                                                    TAG             IMAGE ID       CREATED             SIZE
    centos76                                                      test            ca7db4177ae6   9 seconds ago       810MB
    
    $ docker history centos76:test 
    IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
    ca7db4177ae6   22 seconds ago   /bin/sh -c #(nop) WORKDIR /home/finance         0B        
    903f247275d6   22 seconds ago   /bin/sh -c rm -rf /home/packages && rm -rf /…   25.5MB    
    1dde3ade3113   23 seconds ago   /bin/sh -c #(nop) WORKDIR /                     0B        
    416186ebbcaf   2 hours ago      /bin/sh -c tar -xzvf openssl-1.1.1q.tar.gz &…   145MB     
    cb8526206e1e   2 hours ago      /bin/sh -c tar -xf make-4.2.1.tar.gz && cd m…   12MB      
    5fea9247f155   2 hours ago      /bin/sh -c #(nop) WORKDIR /home/packages        0B        
    07e256259d79   2 hours ago      /bin/sh -c #(nop) ADD file:9872509742c19c105…   200MB     
    8e0a944d4532   2 hours ago      /bin/sh -c yum install -y gcc gcc-c++ vim kd…   225MB     
    6a3b6540b169   2 hours ago      /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B        
    bbd06e461441   3 hours ago      /bin/sh -c #(nop)  LABEL maintainer=jimo 
    f1cb7c7d58b7   3 years ago      /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      3 years ago      /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
    <missing>      3 years ago      /bin/sh -c #(nop) ADD file:54b004357379717df…   202MB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    瘦身之后

    只贴了变化的2层,最后都加了删除操作。

    RUN tar -xf make-4.2.1.tar.gz && cd make-4.2.1 && mkdir build && cd build && ../configure --prefix=/usr && make && make install && rm -rf *
    
    # 安装openssl1.1.1
    RUN tar -xzvf openssl-1.1.1q.tar.gz && cd openssl-1.1.1q \
        && ./config shared --openssldir=/usr/local/openssl --prefix=/usr/local/openssl \
        && make && make install \
        && echo "/usr/local/openssl/lib/" >> /etc/ld.so.conf \
        && ldconfig && rm -rf *
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    结果 684MB,可以看到源码编译openssl层变得很小了,只剩下21.6MB

    $ docker images
    REPOSITORY                                                    TAG             IMAGE ID       CREATED          SIZE
    centos76                                                      test            c1134e4948d8   54 seconds ago   684MB
    
    $ docker history centos76:test 
    IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
    c1134e4948d8   4 seconds ago   /bin/sh -c #(nop) WORKDIR /home/finance         0B        
    2ed7d78e8d90   4 seconds ago   /bin/sh -c rm -rf /home/packages && rm -rf /…   25.5MB    
    98c8b13a2b9b   5 seconds ago   /bin/sh -c #(nop) WORKDIR /                     0B        
    f278729babc4   5 seconds ago   /bin/sh -c tar -xzvf openssl-1.1.1q.tar.gz &21.6MB    
    17bea2739abc   2 minutes ago   /bin/sh -c tar -xf make-4.2.1.tar.gz && cd m…   9.51MB    
    5fea9247f155   2 hours ago     /bin/sh -c #(nop) WORKDIR /home/packages        0B        
    07e256259d79   2 hours ago     /bin/sh -c #(nop) ADD file:9872509742c19c105…   200MB     
    8e0a944d4532   2 hours ago     /bin/sh -c yum install -y gcc gcc-c++ vim kd…   225MB     
    6a3b6540b169   2 hours ago     /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B        
    bbd06e461441   3 hours ago     /bin/sh -c #(nop)  LABEL maintainer=jimo 
    f1cb7c7d58b7   3 years ago     /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B        
    <missing>      3 years ago     /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B        
    <missing>      3 years ago     /bin/sh -c #(nop) ADD file:54b004357379717df…   202MB 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这个优化能有多大

    上面的100多MB看起来无所谓吧,但如果你编译过GCC源码,并且最后没有删掉,你就知道这一层有多大了。

    下面是我编译GCC9.4.0源码产生的镜像层大小, GCC编译万有6个多G,glibc接近1G,足矣引起重视了。

    IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT   
    17c1edbe5d21   6 minutes ago    /bin/sh -c tar -xf glibc-2.33.tar.gz && cd g…   989MB     
    89d80b8e640f   10 minutes ago   /bin/sh -c tar -xvzf gcc-9.4.0.tar.gz && mv6.37GB    
    
    • 1
    • 2
    • 3

    当在结尾加上 rm -rf *后,对应的大小变为几百M,这才是质的提升。

    IMAGE          CREATED             CREATED BY                                      SIZE      COMMENT
    a7e28a9a41aa   2 minutes ago       /bin/sh -c tar -xf glibc-2.33.tar.gz && cd g…   382MB     
    5e0ef78051a0   5 minutes ago       /bin/sh -c tar -xvzf gcc-9.4.0.tar.gz && mv …   779MB
    
    • 1
    • 2
    • 3

    对应的Dockerfile如下:

    RUN tar -xvzf gcc-9.4.0.tar.gz && mv gmp-6.2.1.tar.xz isl-0.24.tar.gz mpc-1.2.1.tar.gz mpfr-4.1.0.tar.gz gcc-9.4.0/ && cd gcc-9.4.0 && tar -xf gmp-6.2.1.tar.xz && \
        tar -xvzf isl-0.24.tar.gz && \
        tar -xvzf mpc-1.2.1.tar.gz && \
        tar -xvzf mpfr-4.1.0.tar.gz && \
        ln -s gmp-6.2.1 gmp && \
        ln -s isl-0.18 isl && \
        ln -s mpc-1.2.1 mpc && \
        ln -s mpfr-4.1.0 mpfr && \
        mkdir build && cd build  && ../configure --prefix=/usr --enable-languages=c,c++ --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --enable-plugin --enable-default-pie --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux --disable-multilib && make -j $(nproc) && make install-strip
    
    RUN tar -xf glibc-2.33.tar.gz && cd glibc-2.33 && \
        mkdir build && cd build && sed -i 's/$name ne "nss_test1"/$name ne "nss_test1" \&\& $name ne "nss_test2"/' ../scripts/test-installation.pl && \
        ../configure --prefix=/usr --enable-obsolete-nsl && make -j $(nproc) && make install
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    总结

    除了删除源码包,系统安装包也要每次RUN就清理, 如果有的话:

    RUN .... && yum clean all && rm -rf *
    RUN .... && yum clean all && rm -rf *
    
    • 1
    • 2

    这算是一个基本操作,以前没注意到是因为对docker镜像的Layer理解不够深刻。

    • 每一条指令都构成一层
    • 每一层都可以看成一个镜像,有唯一的ID
    • 每一层可以缓存,并且可以复用
    • 所以一层定下来后就不能改变了,改了指令就需要重新构建

    在运行时的容器里,所有文件大小不到1G,镜像却有8G,就是因为每一层太大了,虽无用,永留存。

  • 相关阅读:
    SAP KO22内部订单预算BAPI与BDC
    Python杀死Excel?众多模块哪家强
    heketi管理glusterfs,k8s基于glusterfs创建storageclass
    nodejs+vue线上生活超市购物商城系统w2c42
    kube-scheduler源码分析(3)-抢占调度分析
    第二篇 DS5 Armv8 样例工程报错之GCC编译
    【测试开发】一个5年测试开发的成长经验,大学毕业就开启他的职业生涯......
    FL Studio2023水果完整中文版音乐制作软件
    使用消息队列解决RTOS多线程同时打印串口乱序问题
    Nginx 学习(十)高可用中间件的配置与实现
  • 原文地址:https://blog.csdn.net/jimo_lonely/article/details/126251966