一、为什么要做镜像优化?
随着我们对docker镜像的持续使用,在此过程中如果不加以注意并且优化,镜像的体积会越来越大
很多时候我们在使用docker部署应用时,会发现镜像的体积至少有1G以上
镜像体积的增大,不单单会增加磁盘资源与网络资源的开销,也会影响应用的部署效率,使得应用的部署时间会越来越长
因此我们需要减少部署镜像的体积以加快部署效率,降低资源的开销
而对于镜像的优化,可以通过对dockerfile的优化来实现
二、构建镜像的几个原则
镜像最小化原则
-
选择最精简的基础镜像
-
清理镜像构建的中间产物
构建镜像的过程中,当dockerfile的指令执行完成后,删除镜像不需要用的文件。
如使用yum安装组件,可在dockerfile最后用yum clean all镜像清理不需要的文件或者使用系统rm命令删除不需要的源文件等。 -
减少镜像的层数
镜像是一个分层存储的文件,并且镜像对层数也是有一定数量的限制,当前镜像的层数最高是127层,
在使用dockerfile构建镜像时,dockerfile中的每一条指令都会生成一个层,
可以用"&&"将多条命令连接起来。
构建速度最快化原则
- 充分利用镜像构建缓存
镜像父层没有发生变化,构建指令不变,添加文件校验和一致。
只要一个构建指令满足这三个条件,这一层镜像构建就不会再执行,它会直接利用之前构建的结果。
注意:某一层的镜像缓存失效之后,它之后的镜像层缓存都会失效。
我们应该把变化最少的部分放在Dockerfile的前面,这样可以充分利用镜像缓存。
dockerfile中有可能导致缓存失效的命令WORKDIR、CMD、ENV、ADD等,
像这些命令最好放到dockerfile底部,以便在构建镜像过程中最大限度使用缓存。 - 删除构建目录中(默认:Dockerfile所在目录)不需要用的的文件
编写.dockerignore文件过滤构建过程中不必要的文件或者创建单独的目录,并且目录中仅存在镜像构建过程中需要使用的文件。
Docker 在运行时分为 Docker 引擎(也就是服务端守护进程)和客户端工具。 Docker 的引擎提供了一组 REST API,被称为 Docker Remote API, 而如 docker 命令这样的客户端工具,则是通过这组 API 与 Docker引擎交互,从而完成各种功能。 因此,虽然表面上我们好像是在本机执行各种 docker 功能,但实际上,一切都是使用的远程调用形式在服务端(Docker 引擎)完成。
docker build 命令构建镜像,其实并非在本地构建,而是在服务端,也就是 Docker 引擎中构建的。 构建镜像时,Docker需要先准备context,将所有需要的文件收集到进程中。 默认的context包含Dockerfile目录中的所有文件。
如果目录中的存在大量不相关的文件,不仅会导致构建缓慢,而且还会导致镜像体积增大。
优化一(多阶段构建):
/dock/下面有nginx的tar包
ADD与COPY 的区别及用法
1.ADD:源文件可以是压缩文件,并且可以自动解压到目标位置。
————源文件可以是URL(网址),并且可以自动下载并拷贝。
————但是需要注意的是,ADD 指令会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。2.建议尽可能的使用 COPY,因为 COPY 的语义很明确,就是复制文件而已,
而ADD 则包含了更复杂的功能,其行为也不一定很清晰。
3.可以遵循这样的原则:所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。
vim dockerfile
FROM rhel7 as build
COPY dvd.repo /etc/yum.repos.d/
ADD nginx-1.15.8.tar.gz /mnt
WORKDIR /mnt/nginx-1.15.8
RUN rpmdb --rebuilddb && yum install -y gcc make zlib-devel pcre-devel
RUN sed -i ‘s/CFLAGS="$CFLAGS -g"/#CFLAGS="/g’ auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
FROM rhel7
COPY --from=build /usr/local/nginx /usr/local/nginx
EXPOSE 80 #相当于打开容器的80端口,也可以是其他的端口。打开后才能做映射。
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
docker build -t rhel7:nginx .
终极优化:
获取基础镜像:distroless镜像。它只包含应用程序及其运行时依赖项,不包含程序包管理器、shell以及在标准Linux发行版中可以找到的任何其他程序
复制文档下面
https://github.com/kyos0109/nginx-distroless/blob/master/Dockerfile
vim dockerfile
FROM nginx:1.16 as base
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 /usr/sbin/nginx-debug /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/localtime
FROM gcr.io/distroless/base
COPY --from=base /opt /
EXPOSE 80 443
ENTRYPOINT ["nginx", "-g", "daemon off;"]
## 建立镜像
docker build -t rhel7:Bngx .