zoukankan      html  css  js  c++  java
  • docker镜像瘦身思路

    docker镜像瘦身思路

    一、简介

          docker镜像太大,带来了以下几个问题:

    • 存储开销

          这块影响其实不算很大,因为对服务器磁盘来说,15GB的存储空间并不算大,除非用户服务器的磁盘空间很紧张

    • 部署时间

          这块影响真的很大,交付件zip包太大,导致用户部署该产品时,花费的时间变长,客户现场中反馈部署时间超过1.5小时,这严重影响用户的体验,降低满意度

    • 性能不稳定

          如果客户的服务器规格不够(特别是磁盘读写性能不够),会增大部署失败的概率。

    二、瘦身思路

           以下思路是我在该任务中尝试使用用于镜像瘦身的方法,均可以不同程度的降低DOcker镜像的尺寸。

    • 清理Docker镜像中的无用安装包

          在Dockerfile构建Docker镜像过程中,有可能引入临时文件,比如:安装包i、文件压缩包。这些临时文件忘记清理,导致占据了一定的尺寸,有必要对其进行清理。

            如下Dockerfile:   

    FROM xxxx/xxxx-jdk:1.0.0RUN apt-get update && apt-get install -y git maven 
    mysql-client nodejs nodejs-legacy python-pip graphviz npm unzip  

    Dockerfile里面经常安装很多工具,安装完后,需要及时删除安装包缓存

    (alpine) apk del openssh vim:删除包及其依赖包

    (Ubuntu) Apt-get clean:删除所有已下载的包文件

    (centos) Yum clean all: yum 会把下载的软件包和header存储在cache中,而不自动删除。如果觉得占用磁盘空间,可以使用yum clean指令进行清除,更精确 的用法是yum clean headers清除header,yum clean packages清除下载的rpm包,yum clean all一全部清除

          上面的dockerfile中在安装工具后应该执行下: && apt-get clean && rm -rf /var/lib/apt/lists/*

    RUN apt-get update && apt-get install -y git maven 
        mysql-client nodejs nodejs-legacy python-pip graphviz npm unzip && apt-get clean && rm -rf /var/lib/apt/lists/*

       实例:

          

    FROM centos:7
    RUN yum update -y
    RUN yum install -y wget unzip socat java-1.8.0-openjdk-headless
    # Set permissions
    RUN yum clean all
    EXPOSE 8486

       修改:将黄色标示的部分改写成如下,大小从691Mb下降到583Mb

    RUN yum update -y  && yum install -y wget unzip socat java-1.8.0-openjdk-headless && yum clean all
    • 避免不必要的工具安装

         有的Dockerfile中安装了很多工具,这个工具的加在一起尺寸比较大,这块需要挨个排查:客户环境下,需不需要安装该工具?很多工具其实是面向开发使用的,而用户根本不会使用,那么就没有必要在客户环境上使用安装这么工具的镜像,应该仔细排除工具的必要性,会给镜像瘦身带来比较大的收益。比如, dockerfile中安装了JDK。 这个有些情况下,完全没必要,实际上可能jre就能搞定。

         总之,能不安装,就不安装;能少安装,就少安装;能用轻量级的工具,尽量用轻量级的工具!!!

    • 多阶段构建

          Docker多阶段构建是17.05以后引入的新特性,旨在解决编译、构建复杂和镜像大小的问题。对于多阶段构建,可以在Dockerfile中使用多个FROM语句。每个FROM指令可以使用不同的基础,并且每个指令都开始一个新的构建。您可以选择性地将工件从一个阶段复制到另一个阶段,从而在最终image中只留下您想要的内容。

          如下图所示为多阶段构建的使用示例:

    把多个Dockerfile合并在一块,每个Dockerfile单独作为一个“阶段”,“阶段”之间可以互相联系,让后一个阶段构建可以使用前一个阶段构建的产物,形成一条构建阶段的chain,最终结果仅产生一个image,避免产生冗余的多个临时images或临时容器对象。

           1)多阶段构建使用之前

          针对多阶段构建的特点,分析我们产品里面的dockerfile,如下面所示,该操作的目的是将tar包拷贝值容器内的路径下,并解压、执行后续操作。然而COPY层具有一定的大小,只起到临时层的作用。(特别是这个tar包足足几百MB!)。

     

    FROM xxxx:${project.version}COPY karaf-${ccsdk.opendaylight.version}.tar.gz /tmp/
    RUN mkdir /opt/opendaylight 
          && tar zxvf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz --directory /opt/opendaylight && rm -rf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz  
          && mv /opt/opendaylight/karaf-${ccsdk.opendaylight.version} /opt/opendaylight/current && mkdir -p  /opt/opendaylight/current  && ln -s  /opt/opendaylight/current /opt/opendaylight/karaf-${ccsdk.opendaylight.version}
    RUN mkdir -p /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
    COPY mariadb-java-client-${ccsdk.mariadb-connector-java.version}.jar /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
    EXPOSE 8181   

         2)  使用多阶段构建

           使用多阶段构建,修改后的dockerfile如下图所示,修改实现将第一阶段拷贝并解压好的文件复制过来即可,少了拷贝tar包的环节,这样使得最终形成的镜像中镜像层数得到有效的降低,也一定程度上降低了镜像尺寸。

    FROM xxxx:${project.version} as baseFirst
    COPY karaf-${ccsdk.opendaylight.version}.tar.gz /tmp/
    RUN mkdir /opt/opendaylight 
          && tar zxvf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz --directory /opt/opendaylight && rm -rf /tmp/karaf-${ccsdk.opendaylight.version}.tar.gz  
          && mv /opt/opendaylight/karaf-${ccsdk.opendaylight.version} /opt/opendaylight/current 
    
    FROM xxxxxe:${project.version} as baseSecondRUN mkdir -p  /opt/opendaylight/current  && ln -s  /opt/opendaylight/current /opt/opendaylight/karaf-${ccsdk.opendaylight.version}
    COPY --from=baseFirst /opt/opendaylight/current  /opt/opendaylight/current
    RUN mkdir -p /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
    COPY mariadb-java-client-${ccsdk.mariadb-connector-java.version}.jar /opt/opendaylight/current/system/org/mariadb/jdbc/mariadb-java-client/${ccsdk.mariadb-connector-java.version}
    EXPOSE 8181
    • Copy和赋权同时执行
    FROM ubuntu:16.04
    # Copy APIKeys
    COPY ./messageservice/ /tmp/zookeeper/gerrit  ------A 
    EXPOSE 2181 2888 3888
    B------> RUN useradd $ZK_USER && [ `id -u $ZK_USER` -eq 1000 ] && [ `id -g $ZK_USER` -eq 1000 ] && chown -R $ZK_USER:$ZK_USER /opt/$ZK_DIST/ /opt/zookeeper/ /var/lib/ /var/log/ /tmp/zookeeper/    
    USER $ZK_USER

          问题排查如下:A处copy的文件700MB太大,很多文件没用到

                                   B处给/tmp/zookeeper添加属组和属主,该层也很大

           修改:使用 COPY –chown=1000:1000   ./messageservice/ /tmp/zookeeper/gerrit, 镜像大小从1.4GB 下降到700Mb

    • 镜像层的复用

          这一块修改得当的话,得到的收益是最大的!!!最大的!!!最大的!!!

          我们知道docker镜像具有层级结构,如果很多镜像具有相同的层,则这些相同的层就能得到复用(把多个镜像生成一个tar),docker不会保存两份相同放入层文件,通过提高层得复用能显著降低整体的镜像尺寸。比如常见方法有:替换统一的基础镜像、创建出统一的基础镜像、调整层的顺序等等。这里东西没有整理,就不上图了,可以自行脑补,查阅资料即可

    我这边经过这一步调整后,zip产品包从11.45GB下降到6.96GB

    最终zip包从15GB下降到7GB

        

  • 相关阅读:
    阿里架构师说Kafka工作原理归纳,实践通俗易懂!我咋不信呢
    2020做Java的都看这篇文章,面试一次过、升职加薪,赶快来Get
    IDEA最牛配置,众享丝滑
    在IDEA中搭建Java源码学习环境并上传到GitHub上
    Linux基本命令
    正向代理与反向代理
    Spring Boot中使用MyBatis详解
    ftp命令详解
    CentOS7设置中文字符集
    CentOS7计划任务crontab
  • 原文地址:https://www.cnblogs.com/qgbk2018/p/13143841.html
Copyright © 2011-2022 走看看