镜像的优化
- 选择最精简的基础镜像
- 减少镜像的层数
- 清理镜像构建的中间产物
- 注意优化网络请求
- 尽量去用构建缓存
- 使用多阶段构建镜像
一、实例分析
这个是官方的nginx镜像
[root@docker1 docker]# pwd
/tmp/docker
[root@docker1 docker]# ls
Dockerfile nginx-1.15.8.tar.gz web yum.repo
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM rhel7
COPY yum.repo /etc/yum.repos.d/yum.repo
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="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
查看重构的镜像大小:
[root@docker1 docker]# docker images nginx
可以看到有276MB,实在太大了。需要优化。
测试nginx服务是否配置成功:
二、在建立容器时的-V选项和Dockerfile文件中VOLUME的区别
-V 选项
可以直接把指定目录挂载到容器内的一个目录,会覆盖容器内原目录的内容
VOLUME参数
可以把容器内的目录故在到VOLUME卷中,会复制原目录的内容一份到该目录。
VOLUME示例
Dockerfile文件示例:
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM rhel7
COPY yum.repo /etc/yum.repos.d/yum.repo
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="$CFLAGS -g"/g' auto/cc/gcc
RUN ./configure --prefix=/usr/local/nginx
RUN make
RUN make install
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
重构镜像:
[root@docker1 docker]# docker build -t nginx:v2 .
启动容器:
[root@docker1 docker]# docker run -d --name nginx -p 80:80 nginx:v2
ef92524cecc879e2138a9dca8670daaaf028403d73eefff49c1ebb022b65b3f8
查看镜像的层数:
查看管理卷的位置及内容:
[root@docker1 docker]# docker inspect nginx
这个目录挂载到容器的/usr/local/nginx/html目录
我们写一个test文件:
[root@docker1 _data]# pwd
/var/lib/docker/volumes/855b886959c73ec4a7062a73c8e90132ca7cf2993c98453b703fce1f430c1e1d/_data
[root@docker1 _data]# vim test.html
[root@docker1 _data]# cat test.html
<h1>taylor swfit</h1>
[root@docker1 _data]#
浏览器访问:
可以看到使用VOLUME参数后,会直接把容器内目录的内容复制一份到本机上。
三、减少镜像层数、清理镜像构建的中间产物
更改Dockerfile文件:
[root@docker1 _data]# cd /tmp/docker/
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM rhel7
COPY yum.repo /etc/yum.repos.d/yum.repo
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 && 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 -rf /mnt/nginx-1.15.8
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]
重构镜像:
[root@docker1 docker]# docker build -t nginx:v3 .
和之前相比少了26M,可是还是很大。
四、使用多阶段构建镜像
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM rhel7 as build
COPY yum.repo /etc/yum.repos.d/yum.repo
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 && 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 -rf /mnt/nginx-1.15.8
FROM 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@docker1 docker]# docker build -t nginx:v4 .
查看构建镜像的大小:
我们发现使用多阶段构建镜像的效果是很好的。
测试镜像是否可用:
[root@docker1 docker]# docker run -d --name nginx -p 80:80 nginx:v4
b4bea8bfa2d9d2040c9b263399c40869b75495172ac5efe3c9aa7f5c23dc7f2b
可以看到在这个镜像中nginx服务完全是正常的。
五、选择最精简的基础镜像
因为nginx服务,不是用到所有的数据,有的数据是用不到的。要选择最精简的基础镜像来重构镜像,效果会更好!
[root@docker1 ~]# docker load -i distroless.tar
668afdbd4462: Loading layer 18.39MB/18.39MB
Loaded image: gcr.io/distroless/base:latest
[root@docker1 ~]# docker images
可以看到我们现在使用的这个基础镜像只有16.8M,之前的rhel7为140M。
重构镜像:
[root@docker1 ~]# cd /tmp/docker/
[root@docker1 docker]# vim Dockerfile
[root@docker1 docker]# cat Dockerfile
FROM nginx 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/localtime
FROM gcr.io/distroless/base
COPY --from=base /opt /
EXPOSE 80
ENTRYPOINT ["nginx", "-g", "daemon off;"]
重构镜像:
[root@docker1 docker]# docker rm -f nginx
nginx
[root@docker1 docker]# docker build -t nginx:v5 .
可以看到大小仅为23.2M。
启动容器进行测试:
[root@docker1 docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@docker1 docker]# docker run -d --name nginx -p 80:80 nginx:v5
d89029c695c8db863478721c4b40ff1877f582fb42fb8c67e3e81539e1de2bee