Whoosy's Blog

藏巧于拙 用晦而明 寓清于浊 以屈为伸

0%

Dockerfile瘦身优化

编码不易,转载请注意出处!

为什么进行瘦身优化?

减少运维部署成本

现在都讲究快速构建、快速部署,在网络带宽有限的情况下,部署一个1G大小的镜像和100M的镜像带来的时间差距可能就是分钟级和秒级的差距。特别像我们这种公司的私有化服务一样,今天客户机器到公司了,明天市场运营部的人可能就要拉走到客户那边去了,留给我们开发运维去部署和调试的时间少之又少,每个人的服务可能依赖或被依赖于其他人的服务,不能因为一个人还没部署好耽误了整体调试的时间,所以尽量要减少部署的时间,把更多的精力放到联调服务功能上面去。

提高镜像安全性,避免被侵入攻击

最佳的镜像应该只包含应用程序的相关代码文件和依赖,越小的镜像表示无用的程序越少,越不容易受到其他程序漏洞的影响。
最近同事说他阿里云服务器每天都给他发邮件说他个人服务器涉及挖矿,就让我上去看看怎么回事。
查看机器负载CPU持续100%飙满,这绝壁被挖矿了,找到此进程的父进程发现是showdoc容器的启动命令,那应该就是这个容器里的服务有问题,又看了看容器的启动脚本,发现脚本竟然把容器自己的 public key写进宿主机里面去了,修改权限为 600 ,后面容器就可以通过 ssh 直借连接宿主机,怪不得杀死这个挖矿进行过段时间又重启了,没想到容器自己又把这个程序给拉起来了。。。后面修改了下容器启动脚本,就没问题了。

dockerfile-1

dockerfile-2

dockerfile-3

减少存储开销

虽然现在服务器的存储资源比较廉价,但是如果进行整机备份/克隆,那小镜像的优势还是比较明显的。

精简镜像的制作原则

容器运行时使用较小的基础镜像

比如python的项目可以使用python3.x-slim作为基础镜像,此镜像不到60m,而python3.7的镜像就有300多m
dockerfile-4

减少层,去除非必要的文件

​ 在实际制作镜像的过程中,要合理的进行相关层合并,提取出公共缓存层,加速构建。

使用多阶段构建

​ 多阶段构建其实也是减少层的一种,通过多阶段构建,最终镜像可以仅包含最后生成的可执行文件,和必须的运行时依赖,大大减少镜像体积。

​ 以python语言为例,实际运行的过程中只需要最后编译生成的.so文件即可,而如果使用python3.x-slim镜像编译我们的项目代码,是会出问题的,因为此镜像缺少了很多编译时的依赖,比如gcc等库。这时候就可以使用多阶段构建的方式,减少最终生成的镜像体积。

​ 如下是基于python3.7的镜像构建编译代码,通过COPY命令复制到python3.7-slim构建容器运行时的镜像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 基于自建的harbor拉取python3.7镜像进行编译项目
FROM harbor.socmap.net/library/python:3.7
WORKDIR /usr/src/app
COPY ./requirements.txt /usr/src/app
RUN pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ && \
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
COPY . /usr/src/app

# 运行编译脚本
RUN sh build.sh

# 构建容器运行时的镜像
FROM python:3.7-slim
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 PYTHONUNBUFFERED=1
COPY ./sources.list /etc/apt/sources.list
RUN apt update && \
apt-get -y install netcat

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

WORKDIR /usr/src/app
COPY ./requirements.txt /usr/src/app
RUN pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple/ && \
pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/

# 复制python3.7的编译代码
COPY --from=0 /usr/src/app ./

# 运行启动命令
CMD ["/usr/src/app/entrypoint.sh"