docker镜像的优化—多阶段构建镜像

1.优化镜像应该主要有以下几个方面:

  • 选择最精简的基础镜像
  • 减少镜像的层数
  • 清理镜像构建的中间产物
  • 注意优化网络需求
  • 尽量去用构建缓存
2.Docker镜像优化示例 以安装nginx为例
1、未优化
[root@toto6 docker]# docker images rhel7# base镜像 REPOSITORYTAGIMAGE IDCREATEDSIZE rhel7latest0a3eb3fde7fd5 years ago140MB [root@toto6 docker]# ls# build context中必须存在 nginx包 可用的yum源配置文件 Dockerfilenginx-1.15.9.tar.gztoto.repo#Dockerfile文件内容 [root@toto6 docker]# vim Dockerfile FROM rhel7# base镜像 EXPOSE 80# 暴露服务端口 VOLUME ["/usr/local/nginx/html"]# 声明数据卷 ADDnginx-1.15.9.tar.gz /mnt# 导入nginx 源码包 COPY toto.repo /etc/yum.repos.d/toto.repo# 导入yum源配置文件 RUN rpmdb --rebuilddb# 设定yum源 RUN yum install -y gcc pcre-devel zlib-devel make# 安装依赖软件 WORKDIR /mnt/nginx-1.15.9# 切换工作目录 RUN ./configure --prefix=/usr/local/nginx# 编译nginx RUN make RUN make install# 安装nignx CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off; "]# 运行nginx

创建镜像并查看镜像大小
[root@toto6 docker]# docker build -t nginx:v1 .[root@toto6 docker]# docker images REPOSITORYTAGIMAGE IDCREATEDSIZE nginxv1c4712dcc2963About a minute ago295MB rhel7latest0a3eb3fde7fd5 years ago140MB

未经过优化的生成的镜像295M
2、 清理中间缓存并尽量减少镜像层数
[root@toto6 docker]# vim Dockerfile FROM rhel7 EXPOSE 80 VOLUME ["/usr/local/nginx/html"] ADDnginx-1.15.9.tar.gz /mnt COPY toto.repo /etc/yum.repos.d/toto.repo WORKDIR /mnt/nginx-1.15.9 RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && yum clean all && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx && make && make install CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off; "]

创建镜像并查看镜像大小
[root@toto6 docker]# docker build -t nginx:v2 .[root@toto6 docker]# docker images REPOSITORYTAGIMAGE IDCREATEDSIZE nginxv22b20e470e31c25 seconds ago252MB nginxv1c4712dcc296311 minutes ago295MB rhel7latest0a3eb3fde7fd5 years ago140MB

【docker镜像的优化—多阶段构建镜像】本次缩减镜像到252M
3、使用多阶段构建方法 我们需要的只不过是编译之后的软件包,那么我们就可以在一容器编译安装以后,将编译安装之后的安装包拷贝到另一个容器中,这样就减小了不需要的开销。并且将压缩包删除。
[root@toto6 docker]# vim Dockerfile FROM rhel7 as build# 这一阶段只需需要完成nginx的编译 ADD nginx-1.15.9.tar.gz /mnt COPY toto.repo /etc/yum.repos.d/toto.repo WORKDIR /mnt/nginx-1.15.9 RUN rpmdb --rebuilddb && yum install -y gcc pcre-devel zlib-devel make && yum clean all && sed -i 's/CFLAGS="$CFLAGS -g"/#CFLAGS="$CFLAGS -g"/g' auto/cc/gcc && ./configure --prefix=/usr/local/nginx && make && make install && rm -fr /mnt/nginx-1.15.8FROM rhel7# 创建镜像,将编译好的文件直接拿过来用 COPY --from=build /usr/local/nginx /usr/local/nginx EXPOSE 80 VOLUME ["/usr/local/nginx/html"] CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off; "]

创建镜像并查看镜像大小
[root@toto6 docker]# docker build -t nginx:v3 .[root@toto6 docker]# docker images REPOSITORYTAGIMAGE IDCREATEDSIZE nginxv3e5b90394203319 seconds ago141MB nginxv22b20e470e31c11 minutes ago252MB nginxv1c4712dcc296322 minutes ago295MB rhel7latest0a3eb3fde7fd5 years ago140MB

此时发现镜像大小已经为141MB了,但是rhel7的基础镜像大小为140MB。所以我们使用的时候就可以发现基础镜像其实不需要这么多。所以可以添加更小的基础镜像
4、减少底层base的大小
使用一个最基础的系统环境镜像。然后从nginx进行中将运行nginx所需要的依赖库都导入到基础的系统镜像中,就可以满足运行nginx的要求。做到最小化。
docker load -i distroless.tar##一个基础的系统环境镜像 docker load -i nginx.tar##nginx的进行,vim Dockerfile FROM nginx:1.16 as base # https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ARG Asia/Shanghai RUN mkdir -p /opt/var/cache/nginx && \ cp -a --parents /usr/lib/nginx /opt && \ cp -a --parents /usr/share/nginx /opt && \ cp -a --parents /var/log/nginx /opt && \ cp -aL --parents /var/run /opt && \ cp -a --parents /etc/nginx /opt && \ cp -a --parents /etc/passwd /opt && \ cp -a --parents /etc/group /opt && \ cp -a --parents /usr/sbin/nginx /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libpcre.so.* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libdl.so.* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libpthread.so.* /opt && \ cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /opt && \ cp -a --parents /usr/lib/x86_64-linux-gnu/libssl.so.* /opt && \ cp -a --parents /usr/lib/x86_64-linux-gnu/libcrypto.so.* /opt && \ cp /usr/share/zoneinfo/${TIME_ZONE:-ROC} /opt/etc/localtimeFROM gcr.io/distroless/base COPY --from=base /opt / EXPOSE 80 VOLUME ["/usr/share/nginx/html"] ENTRYPOINT ["nginx", "-g", "daemon off; "]

创建镜像并查看镜像大小
[root@toto6 docker]# docker images REPOSITORYTAGIMAGE IDCREATEDSIZE nginxv4cb475e8f44127 seconds ago23.7MB nginxv3e5b90394203319 minutes ago141MB nginx1.16ac44715da54a4 weeks ago109MB rhel7latest0a3eb3fde7fd5 years ago140MB gcr.io/distroless/baselatest9a255d5fe26249 years ago16.8MB

到次nginx镜像被压缩到23.7M

    推荐阅读