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