Docker玩法 — 镜像优化之旅
Docker玩法 — 镜像优化之旅开门见山地说,如果你已经来着这里,肯定发现了这个问题,我们在做镜像的时候,仅仅几K的源文件打出来居然百兆以上!更有甚者能到1个G,这无疑在后期运用时产生较大影响,所以我们这次主要目的就是给镜像减肥。准备沿用前一篇Go服务为例,首先看一下我们的源码大小,大概1K左右,打包服务后整体6M左右我们用 golang 作为宿主环境构建dockerfileFROM golan
Docker玩法 — 镜像优化之旅
开门见山地说,如果你已经来着这里,肯定发现了这个问题,我们在做镜像的时候,仅仅几K的源文件打出来居然百兆以上!更有甚者能到1个G,这无疑在后期运用时产生较大影响,所以我们这次主要目的就是给镜像减肥。
准备
沿用前一篇Go服务为例,首先看一下我们的源码大小,大概1K左右,打包服务后整体6M左右
我们用 golang 作为宿主环境构建dockerfile
FROM golang:latest
MAINTAINER xiao4_800k <840076909@qq.com>
WORKDIR /go/src/goservice
ADD goservice/ /go/src/goservice
RUN go build -o .
EXPOSE 80
CMD ["./goservice"]
编译goservice镜像,我们看到他的大小为 852MB ,是不是感觉非常的差异,从源码1k到852MB,差距如此之大,咱们的源码到底经历了些什么?
第一站,探究本源
万事皆有因果,有什么因得什么果,想要弄清楚如何优化,我们必须探究一下是什么原因造成了镜像如此之大。
接下来我们做一个实验,思路如下:我们向ubuntu镜像中增加文件,再通过命令删除文件,按照我们的理解这时最终的镜像大小应该为ubuntu的大小,因为里面没有任何文件了,对吗?测试一下。
首先我们查看需要使用的文件大小
书写dockerfile
FROM ubuntu
ADD goservice/GoService.exe .
RUN rm GoService.exe
编译镜像,并查看最终的生成结果
通过实验我们看到这样的数据,最终的test镜像并不是我们预期的大小,这是为什么那?
这还要从dockerfile文件说起,前篇我们提过,docker是容器,是运行服务得环境,为了保证容器之间互补干扰,所以每个容器都有相对独立的环境,即使是空环境也是相对独立的,也就是说镜像中必定包含一个能够运行服务的环境;我们再来说一下dockerfile的命令,基本上每一条命令站一行,而行号而则是运行的命令的规则,由上至下的,这也就是docker中层的概念,也就是说为了保证镜像的完整性,docker会将每一层都保存起来,而镜像的大小也就是层大小的总和。
所以我们刚刚的镜像大小就是 三层之和
第一层ubuntu的大小72.9M
第二层追加exe的大小为6.1M
第三层删除命令忽略不计
所以总和为 72.9 + 6.1 约等于 79M
第二站,优化结构
我们弄清楚原因后,那我们就可以修改我们之前的服务了,为了能让go服务的镜像更小,我们先要找到它能到800M的原因,我们查看一下golang有多大
这样我们就知道大部分原因就在这里了,宿主太大了,那么我们换一下宿主就可以完美减肥了对吗?而ubuntu可以说还算不错的选择,那么我们重新编写我们的dockerfile文件
FROM golang:latest
WORKDIR /go/src/goservice
ADD goservice/ /go/src/goservice
RUN go build .
FROM ubuntu:latest
WORKDIR /usr/local/goservice
COPY --from=0 /go/src/goservice /usr/local/goservice
EXPOSE 80
CMD ["./goservice"]
这里我们使用Linux系统编译我们的镜像,否则需要配置交叉编译
查看最终镜像大小从800+M缩减至80M,大小已经缩减至我们能够接受的大小了,现在运行镜像也可以正常访问到了
第三站,追求极致
至此,我们已经基本上达到了我们预期效果,但是对于我们这种追求极致的人来说,是不是可以在优化一下那?调整我们的dockerfile文件
FROM scratch
ADD /goservice /goservice
ENTRYPOINT ["/goservice"]
这里使用scratch空镜像作为宿主环境,将编译后的服务goservice追加到宿主环境,最后开始镜像编译,得到如下结果,可以看到我们最后的镜像已经接近服务本身大小6M左右,可以说非常满意了,如果还是不满足,那就需要在服务编译过程中在进行优化了
终点站
那么我们这趟旅行就这样结束了,对于docker而言,需要经常去尝试,在各种错误中积累自己的经验,这样才会对它有更深刻的理解,在后续使用中可能我们会将很多服务都加入到docker中,少量的时候察觉不到什么,当容器超过几十个或上百个的时候我们该如何做到更好的管理那?那当是……后续在讲吧
更多推荐
所有评论(0)