手把手教学优化docker镜像构建,使构建的镜像比官网的还小巧轻便 Dockerfile

为什么要docker减小镜像?

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

初学者常规构建

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

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

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

 Dockerfile事例:

FROM centos:7
ENV PROJECT_PATH=/opt
WORKDIR ${PROJECT_PATH}
ADD nginx-1.22.1.tar.gz .
RUN /bin/sh -c "yum -y update"
RUN /bin/sh -c "yum -y install openssl-devel"
RUN /bin/sh -c "yum -y install pcre-devel"
RUN /bin/sh -c "yum -y install gcc"
RUN /bin/sh -c "yum -y install make"
ENV PROJECT_PATH=/opt/nginx-1.22.1
WORKDIR ${PROJECT_PATH}
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"
RUN /bin/sh -c "make"
RUN /bin/sh -c "make install"
EXPOSE 80
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 缓存

FROM centos:7
ENV PROJECT_PATH=/opt
WORKDIR ${PROJECT_PATH}
ADD nginx-1.22.1.tar.gz .
RUN /bin/sh -c "yum -y update"
RUN /bin/sh -c "yum -y install openssl-devel"
RUN /bin/sh -c "yum -y install pcre-devel"
RUN /bin/sh -c "yum -y install gcc"
RUN /bin/sh -c "yum -y install make"
ENV PROJECT_PATH=/opt/nginx-1.22.1
WORKDIR ${PROJECT_PATH}
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"
RUN /bin/sh -c "make"
RUN /bin/sh -c "make install"
ENV PROJECT_PATH=/usr/local/nginx
WORKDIR ${PROJECT_PATH}
# 删除nign源码,卸载构建工具,清除yum缓存
RUN /bin/sh -c "rm -rf /opt/nginx-1.22.1"
RUN /bin/sh -c "yum -y remove openssl-devel"
RUN /bin/sh -c "yum -y remove pcre-devel"
RUN /bin/sh -c "yum -y remove gcc"
RUN /bin/sh -c "yum -y remove make"
RUN /bin/sh -c "yum clean all"
RUN /bin/sh -c "yum clean packages"
EXPOSE 80
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文件中也是可以这样使用的,把所有的命令放到一层中。

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

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

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

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

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

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

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

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

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

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

dockerfile事例:centos构建,ubuntu 运行

# stage-1
FROM centos:7 as build
ENV PROJECT_PATH=/opt
WORKDIR ${PROJECT_PATH}
ADD nginx-1.22.1.tar.gz .
RUN /bin/sh -c "yum -y update && \
    yum -y install openssl-devel pcre-devel gcc make && \
    cd /opt/nginx-1.22.1 && \
    ./configure --prefix=/usr/local/nginx --sbin-path=/bin/ --with-http_ssl_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre && \
    make && make install &&  \
    cd /usr/local/nginx && \
    rm -rf /opt/nginx-1.22.1 && \
    yum -y remove openssl-devel pcre-devel gcc make && \
    yum clean all && yum clean packages"
# stage-2
FROM ubuntu:latest
COPY --from=build /usr/local/nginx /usr/local/nginx
COPY --from=build /bin/nginx /bin/nginx
COPY --from=build /lib64/libpcre.so.1 /lib/x86_64-linux-gnu/libpcre.so.1
COPY --from=build /lib64/libssl.so.10 /lib/x86_64-linux-gnu/libssl.so.10
COPY --from=build /lib64/libcrypto.so.10 /lib/x86_64-linux-gnu/libcrypto.so.10
RUN /bin/sh -c "sed -i 's/#user  nobody;/user  nobody nogroup;/' /usr/local/nginx/conf/nginx.conf"
EXPOSE 80
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,或者更小镜像,估计会更小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值