1.优化镜像应该主要有以下几个方面:
- 选择最精简的基础镜像
- 减少镜像的层数
- 清理镜像构建的中间产物
- 注意优化网络需求
- 尽量去用构建缓存
2.Docker镜像优化示例
以安装nginx为例
1、未优化
[root@toto6 docker]# docker images rhel7 # base镜像
REPOSITORY TAG IMAGE ID CREATED SIZE
rhel7 latest 0a3eb3fde7fd 5 years ago 140MB
[root@toto6 docker]# ls # build context中必须存在 nginx包 可用的yum源配置文件
Dockerfile nginx-1.15.9.tar.gz toto.repo
#Dockerfile文件内容
[root@toto6 docker]# vim Dockerfile
FROM rhel7 # base镜像
EXPOSE 80 # 暴露服务端口
VOLUME ["/usr/local/nginx/html"] # 声明数据卷
ADD nginx-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
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v1 c4712dcc2963 About a minute ago 295MB
rhel7 latest 0a3eb3fde7fd 5 years ago 140MB
未经过优化的生成的镜像295M
2、 清理中间缓存并尽量减少镜像层数
[root@toto6 docker]# vim Dockerfile
FROM rhel7
EXPOSE 80
VOLUME ["/usr/local/nginx/html"]
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
CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
创建镜像并查看镜像大小
[root@toto6 docker]# docker build -t nginx:v2 .
[root@toto6 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v2 2b20e470e31c 25 seconds ago 252MB
nginx v1 c4712dcc2963 11 minutes ago 295MB
rhel7 latest 0a3eb3fde7fd 5 years ago 140MB
本次缩减镜像到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.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@toto6 docker]# docker build -t nginx:v3 .
[root@toto6 docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v3 e5b903942033 19 seconds ago 141MB
nginx v2 2b20e470e31c 11 minutes ago 252MB
nginx v1 c4712dcc2963 22 minutes ago 295MB
rhel7 latest 0a3eb3fde7fd 5 years ago 140MB
此时发现镜像大小已经为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/localtime
FROM 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
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx v4 cb475e8f4412 7 seconds ago 23.7MB
nginx v3 e5b903942033 19 minutes ago 141MB
nginx 1.16 ac44715da54a 4 weeks ago 109MB
rhel7 latest 0a3eb3fde7fd 5 years ago 140MB
gcr.io/distroless/base latest 9a255d5fe262 49 years ago 16.8MB