当前位置:   article > 正文

手把手教学优化docker镜像构建,使构建的镜像比官网的还小巧轻便 Dockerfile_dockerfile 使镜像更小需要注意的事项

dockerfile 使镜像更小需要注意的事项

为什么要docker减小镜像?

        在使用docekrfile文件构建docker镜像时,即使时安装一个比较小的应用,构建后也是镜像,小到好几百M大到几个G, 这样非常不利与镜像之间的传输与上传到镜像仓库,部署的时候也会浪费时间,安装更多的工具会导致构建的镜像安全系数大幅度降低。

初学者常规构建

        在刚学习dockerfile构建镜像的时候,我们的docker文件一般都是 RUN,命令行一行的写,这样会导致每个RUN命令就会创建一个layer层,从而增大镜像的大小。例如:

使用nginx源码进行构建nginx, 基础镜像使用centos:7 大约200M,使用du -sh nginx,可以查看nginx的大小只有1M多一点。如果构建的镜像非常大,那是用容器就没必要了。

  1. [root@localhost nginx_docker]# du -sh nginx-1.22.1.tar.gz
  2. 1.1M nginx-1.22.1.tar.gz

 Dockerfile事例:

  1. FROM centos:7
  2. ENV PROJECT_PATH=/opt
  3. WORKDIR ${PROJECT_PATH}
  4. ADD nginx-1.22.1.tar.gz .
  5. RUN /bin/sh -c "yum -y update"
  6. RUN /bin/sh -c "yum -y install openssl-devel"
  7. RUN /bin/sh -c "yum -y install pcre-devel"
  8. RUN /bin/sh -c "yum -y install gcc"
  9. RUN /bin/sh -c "yum -y install make"
  10. ENV PROJECT_PATH=/opt/nginx-1.22.1
  11. WORKDIR ${PROJECT_PATH}
  12. RUN /bin/sh -c "./configure --prefix=/usr/local/nginx --sbin-path=/bin/ --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre"
  13. RUN /bin/sh -c "make"
  14. RUN /bin/sh -c "make install"
  15. EXPOSE 80
  16. ENTRYPOINT ["nginx", "-g", "daemon off;"]

        分析:一共构建了17镜像层,因为一共17行命令,构建后的镜像大小一共是1.4GB,Oh My God!, 为什么会那么大,可以使用docker history nginx:v1检查一下每一步构建的大小。虽然使用docker run 启动也是没问题的,但是传输也太不方便了。

优化方法:

1、安装后删除软件包(不推荐)

        因为在构建的时候我们使用yum 安装装了好多构建包,而且还有nginx源码也存在镜像中,那么我们删除可以删除这些包,并且清除yum的环境,因为编译安装后的nginx是不需要这些包的。尝试一下

1)删除nginx的源码文件

2)卸载构建是的工具包, 如:gcc make oepssl-devel pcre-devel 

3)清除yum 缓存

  1. FROM centos:7
  2. ENV PROJECT_PATH=/opt
  3. WORKDIR ${PROJECT_PATH}
  4. ADD nginx-1.22.1.tar.gz .
  5. RUN /bin/sh -c "yum -y update"
  6. RUN /bin/sh -c "yum -y install openssl-devel"
  7. RUN /bin/sh -c "yum -y install pcre-devel"
  8. RUN /bin/sh -c "yum -y install gcc"
  9. RUN /bin/sh -c "yum -y install make"
  10. ENV PROJECT_PATH=/opt/nginx-1.22.1
  11. WORKDIR ${PROJECT_PATH}
  12. RUN /bin/sh -c "./configure --prefix=/usr/local/nginx --sbin-path=/bin/ --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre"
  13. RUN /bin/sh -c "make"
  14. RUN /bin/sh -c "make install"
  15. ENV PROJECT_PATH=/usr/local/nginx
  16. WORKDIR ${PROJECT_PATH}
  17. # 删除nign源码,卸载构建工具,清除yum缓存
  18. RUN /bin/sh -c "rm -rf /opt/nginx-1.22.1"
  19. RUN /bin/sh -c "yum -y remove openssl-devel"
  20. RUN /bin/sh -c "yum -y remove pcre-devel"
  21. RUN /bin/sh -c "yum -y remove gcc"
  22. RUN /bin/sh -c "yum -y remove make"
  23. RUN /bin/sh -c "yum clean all"
  24. RUN /bin/sh -c "yum clean packages"
  25. EXPOSE 80
  26. ENTRYPOINT ["nginx", "-g", "daemon off;"]

        分析:使用docker images 查看构建的nginx:v2镜像的大小比第一次构建的nginx:v1镜像还大,为什么呢,我们使用docker history nginx:v2 查看构建步骤,足足有20多层,而且后边使用RUN命令的时候每增加一个就会增加24M左后,所以不减反增。

 小结:除非是很大的文件需要删除,才推荐加RUN命令,否者会事半功倍的。

2、最小化镜像层(强烈推荐)

        因为dockerfile文件中每一个镜像的命令如ADD COPY  RUN,都会是一个镜像层,可以减少这些镜像命令的使用。在Linux操作系统中,可以使用 && 符合连接两个命令,可以使用 \ 进行长命令换行,在Dockerfile文件中也是可以这样使用的,把所有的命令放到一层中。

  1. FROM centos:7
  2. ENV PROJECT_PATH=/opt
  3. WORKDIR ${PROJECT_PATH}
  4. ADD nginx-1.22.1.tar.gz .
  5. RUN /bin/sh -c "yum -y update && \
  6. yum -y install openssl-devel pcre-devel gcc make && \
  7. cd /opt/nginx-1.22.1 && \
  8. ./configure --prefix=/usr/local/nginx --sbin-path=/bin/ --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre && \
  9. make && make install && \
  10. cd /usr/local/nginx && \
  11. rm -rf /opt/nginx-1.22.1 && \
  12. yum -y remove openssl-devel pcre-devel gcc make && \
  13. yum clean all && yum clean packages"
  14. EXPOSE 80
  15. ENTRYPOINT ["nginx", "-g", "daemon off;"]

       与上一个dockerfile 相比 我们把所有的RUN 命令都合并到了一个RUN 命令里面,命令操作都是一样的。使用docker images命令查看镜像大小,docker history 查看镜像的构建步骤,镜像nginx:v3大约400M,比刚才的 nginx:v1,  1.4G 减少了3-4倍。

 分析:因为我们把所有的RUN 命令都放到了同一个RUN命令中,在实际的构建过程中,相当于把好几层压缩到了一层。

小结:这种方法可以大幅度减小镜像的大小。

3、使用多阶段构建镜像(推荐)

        所谓的多阶段构建就是至少有两个阶段,第一阶段是编译应用,第二阶段就是运行,将第一个阶段编译好的应用跑在第二个阶段上。原因,第一个阶段上有很多编译的工具不一定能完全卸载删除。而应用运行的时候又不依赖这些编译工具。所以编译工具就是多余的。

  1. # stage-1
  2. FROM centos:7 as build
  3. ENV PROJECT_PATH=/opt
  4. WORKDIR ${PROJECT_PATH}
  5. ADD nginx-1.22.1.tar.gz .
  6. RUN /bin/sh -c "yum -y update && \
  7. yum -y install openssl-devel pcre-devel gcc make && \
  8. cd /opt/nginx-1.22.1 && \
  9. ./configure --prefix=/usr/local/nginx --sbin-path=/bin/ --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre && \
  10. make && make install && \
  11. cd /usr/local/nginx && \
  12. rm -rf /opt/nginx-1.22.1 && \
  13. yum -y remove openssl-devel pcre-devel gcc make && \
  14. yum clean all && yum clean packages"
  15. # stage-2
  16. FROM centos:7
  17. COPY --from=build /usr/local/nginx /usr/local/nginx
  18. COPY --from=build /bin/nginx /bin/nginx
  19. EXPOSE 80
  20. ENTRYPOINT ["nginx", "-g", "daemon off;"]

        分析:与上一个nginx:v3相比 我们使用的多阶段构建,第一个阶段构建nginx,第二个阶段运行nginx。使用docker images命令查看镜像大小,docker history 查看镜像的构建步骤。nginx:v4 镜像的大小只有210M,, 只比基础镜像多了6M,运行也是没有问题的。简直不要太爽。

小结:这种方法也是可以大成倍的减少镜像的大小。

4、使用比较小的基础镜像(比较推荐:但是有时环境不同,会缺少动态链接库)

dockerfile事例:centos构建,ubuntu 运行

  1. # stage-1
  2. FROM centos:7 as build
  3. ENV PROJECT_PATH=/opt
  4. WORKDIR ${PROJECT_PATH}
  5. ADD nginx-1.22.1.tar.gz .
  6. RUN /bin/sh -c "yum -y update && \
  7. yum -y install openssl-devel pcre-devel gcc make && \
  8. cd /opt/nginx-1.22.1 && \
  9. ./configure --prefix=/usr/local/nginx --sbin-path=/bin/ --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre && \
  10. make && make install && \
  11. cd /usr/local/nginx && \
  12. rm -rf /opt/nginx-1.22.1 && \
  13. yum -y remove openssl-devel pcre-devel gcc make && \
  14. yum clean all && yum clean packages"
  15. # stage-2
  16. FROM ubuntu:latest
  17. COPY --from=build /usr/local/nginx /usr/local/nginx
  18. COPY --from=build /bin/nginx /bin/nginx
  19. COPY --from=build /lib64/libpcre.so.1 /lib/x86_64-linux-gnu/libpcre.so.1
  20. COPY --from=build /lib64/libssl.so.10 /lib/x86_64-linux-gnu/libssl.so.10
  21. COPY --from=build /lib64/libcrypto.so.10 /lib/x86_64-linux-gnu/libcrypto.so.10
  22. RUN /bin/sh -c "sed -i 's/#user nobody;/user nobody nogroup;/' /usr/local/nginx/conf/nginx.conf"
  23. EXPOSE 80
  24. ENTRYPOINT ["nginx", "-g", "daemon off;"]

        寻找比较小的基础镜像代替centos:7,例如使用ubuntu基础镜像,代替nginx运行,还可以使用alpine 基础镜像, 也可以使用google的debian,构建完之后的镜像要更小。

         使用 ubuntu 作为第二阶段的运用来构建nginx镜像。使用ubuntu之后构建完之后的镜像大小只有83.9M,还不到100M,但是运行nginx命令会出现找不到动态链接的报错信息,进入镜像,使用ldd 查看启动nginx 需要的动态链接库有哪些,需要从第一阶段的环境中COPY过来。

 使用docker run 运行构建的镜像,运行结果OK,

        总结:以上是几个项目构建中的常用优化方法,其它的方法也有,例如使用一些开源三方库检测dockerfile文件。但是不是很推荐,掌握好基础比较重要。我们第一次构建的镜像大约 1.4个G ,使用最小层构建的大约400M,使用多阶段构建的大约200M,使用 多阶段+小基础镜像构建的大约只有85M,这是因为ubuntu镜像基础大小为78M,如果使用apline,或者更小镜像,估计会更小。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/58017
推荐阅读
相关标签
  

闽ICP备14008679号