2018-09-24 01:01:46
实测有效方法:压缩你的镜像
方法:试着用命令或工具压缩你的镜像。
doc ker 自带的一些命令还能协助压缩镜像,比如 export 和 import
$ doc ker run -d redis:lab-3
$ doc ker export 71b1c0ad0a2b | doc ker import - redis:lab-4
但麻烦的是需要先将容器运行起来,而且这个过程中你会丢失镜像原有的一些信息,比如:导出端口,环境变量,默认指令。
doc kerinfo.net/2016/10/20161027203227.jpg" sizes="(max-width: 650px) 100vw, 650px" data-originalset="http://img.doc kerinfo.net/2016/10/20161027203227.jpg 650w, http://img.doc kerinfo.net/2016/10/20161027203227-300x247.jpg 300w" alt="20161027203227" width="650" height="535" data-tag="bdshare" />
介绍
前段时间网易蜂巢曾经推出蜂巢 Logo T恤,用的正是 Docker 镜像制作,最神奇的是,它最终的镜像大小只有 585字节。
$ doc ker images | grep hub . c . 163.com / public / logo
REPOSITORY TAG IMAGE ID CREATED SIZE
hub . c . 163.com / public / logo latest 6fbdd13cd204 11 days ago 585 B
这其中就用到了不少精简镜像的技术,尤其是针对 C 程序的优化和精简。但我们平常开发肯定不止用 C 语言,甚至有些镜像都不是我们自己来打包的(比如下载公共镜像),那是否有一些通用的精简 Docker 镜像的手段呢? 答案是肯定的 ,甚至有的镜像可以精简 98%。精简镜像大小的好处不言而喻,既节省了存储空间,又能节省带宽,加快传输。那好,接下来就请跟随我来学习怎么一步步精简 Docker 镜像吧。
镜像层(Layers)
在开始制作镜像之前,首先了解下镜像的原理,而这其中最重要的概念就是镜像层(Layers)。镜像层依赖于一系列的底层技术,比如文件系统(filesystems)、写时复制(copy-on-write)、联合挂载(union mounts)等,幸运的是你可以在很多地方学习到这些技术,这里就不再赘述技术细节。
doc kerinfo.net/2016/10/20161027203243.jpg" sizes="(max-width: 545px) 100vw, 545px" data-originalset="http://img.doc kerinfo.net/2016/10/20161027203243.jpg 545w, http://img.doc kerinfo.net/2016/10/20161027203243-300x241.jpg 300w" alt="20161027203243" width="545" height="438" data-tag="bdshare" />
总的来说,你最需要记住这点:
在 Dockerfile 中, 每一条指令都会创建一个镜像层,继而会增加整体镜像的大小。
举例来说:
FROM busybox
RUN mkdir / tmp / foo
RUN dd if = /dev/ zero of = /tmp/ foo / bar bs = 1048576 count = 100
RUN rm / tmp / foo / bar
以上 Dockerfile 干了这几件事:
基于一个官方的基础镜像 busybox(只有1M多)
创建一个文件夹(/tmp/foo)和一个文件(bar)
为该文件分配了100M大小
再把这个大文件删除
事实上,它最终什么也没做,我们把它构建成镜像看看(构建可以参考一期):
doc ker build - t busybox : test .
再让我们来对比下原生的 busybox 镜像大小和我们生成的镜像大小:
$ doc ker images | grep
busyboxbusybox test 896c63dbdb96 2 seconds ago 106 MB
busybox latest 2b8fd9751c4c 9 weeks ago 1.093 MB
出乎意料的是,却生成了 106 MB 的镜像。
多出了 100 M,这是为何?这点和 git 类似(都用到了Copy-On-Write技术),我用 git 做了如下两次提交(添加了又删除),请问 A_VERY_LARGE_FILE 还在 git 仓库中吗?
$ git add A_VERY_LARGE_FILE
$ git commit
$ git rm A_VERY_LARGE_FILE
$ git commit
答案是: 在的 ,并且会占用仓库的大小。Git 会保存每一次提交的文件版本,而 Dockerfile 中每一条指令都可能增加整体镜像的大小,即使它最终什么事情都没做。
精简步骤
了解了镜像层知识,有助于我们接下来制作精简镜像。这里开始,以最常用的开源缓存软件 Redis 为例,从一步步试验,来介绍如何制作更精简的 doc kerinfo.net/doc kerimages" target="_blank">Docker 镜像 。
步骤 1:初始化构建 Redis 镜像
直接上 doc kerinfo.net/doc kerfile" target="_blank">Dockerfile :
FROM ubuntu : trusty
ENV VER 3.0 . 0
ENV TARBALL http : //download.redis.io/releases/redis-$VER.tar.gz
# ==> Install curl and helper tools...
RUN apt - get update
RUN apt - get install - y curl make gcc
# ==> Download, compile, and install...
RUN curl - L $TARBALL | tar zxv
WORKDIR redis - $VER
RUN make
RUN make install
#...
# ==> Clean up...
WORKDIR /
RUN apt - get remove - y -- auto - remove curl make gcc
RUN apt - get clean
RUN rm - rf / var / lib / apt / lists /* /redis-$VER
#...
CMD ["redis-server"]
结合注释,读起来并不困难,用到的都是常规的几个命令,简要介绍如下:
FROM:顶头写,指定一个基础镜像,此处基于 ubuntu:trusty
ENV:设置环境变量,这里设置了 VER 和 TARBALL 两个环境变量
RUN:最常用的 Dockerfile doc kerinfo.net/341.html" target="_blank">指令 ,用于运行各种命令,这里调用了 8 次 RUN 指令
WORKDIR:指定工作目录,相当于指令 cd
CMD:指定镜像默认执行的命令,此处默认执行 redis-server 命令来启动 redis
执行构建:
$ doc ker build - t redis : lab - 1 .
注:国内网络,更新下载可能会较慢
查看大小:
doc kerinfo.net/2016/10/20161027203303.jpg" sizes="(max-width: 435px) 100vw, 435px" data-originalset="http://img.doc kerinfo.net/2016/10/20161027203303.jpg 435w, http://img.doc kerinfo.net/2016/10/20161027203303-300x62.jpg 300w" alt="20161027203303" width="435" height="90" data-tag="bdshare" />
动辄就有 300多 M 的大小,不能忍,下面我们开始一步步优化。
步骤 2: 优化基础镜像
方法:选用更小的基础镜像。
常用的 Linux 系统镜像一般有 ubuntu、centos、debian,其中debian 更轻量,而且够用,对比如下:
REPOSITORY TAG IMAGE ID VIRTUAL SIZE
--------------- ------ ------------ ------------
centos 7 214a4932132a 215.7 MB
centos 6 f6808a3e4d9e 202.6 MB
ubuntu trusty d0955f21bf24 188.3 MB
ubuntu precise 9c5e4be642b7 131.9 MB
debian jessie 65688f7c61c4 122.8 MB
debian wheezy 1265e16d0c28 84.96 MB
替换 debian:jessie 作为我们的基础镜像。
优化 Dockerfile:
FROM debian : jessie
#...
执行构建:
$ doc ker build - t redis : lab - 2 .
查看大小:
doc kerinfo.net/2016/10/20161027203254.jpg" sizes="(max-width: 441px) 100vw, 441px" data-originalset="http://img.doc kerinfo.net/2016/10/20161027203254.jpg 441w, http://img.doc kerinfo.net/2016/10/20161027203254-300x91.jpg 300w" alt="20161027203254" width="441" height="134" data-tag="bdshare" />
减少了42M,稍有成效,但并不明显。细心的同学应该发现,只有 122 MB 的 debian 基础镜像,构建后增加到了 305 MB,看来这里面肯定有优化的空间,如何优化就要用到我们开头说到的 Image Layer 知识了。
步骤 3:串联 Dockerfile 指令
方法: 串联你的 Dockerfile 指令(一般是 RUN 指令)。
Dockerfile 中的 RUN 指令通过 && 和 / 支持将命令串联在一起,有时能达到意想不到的精简效果。
优化 Dockerfile:
FROM debian : jessie
ENV VER 3.0 . 0
ENV TARBALL http : //download.redis.io/releases/redis-$VER.tar.gz
RUN echo "==> Install curl and helper tools..." && \ apt - get update && \
apt - get install - y curl make gcc && \
\
echo "==> Download, compile, and install..." && \
curl - L $TARBALL | tar zxv && \
cd redis - $VER && \
make && \
make install && \
...
echo "==> Clean up..." && \
apt - get remove - y -- auto - remove curl make gcc && \
apt - get clean && \
rm - rf / var / lib / apt / lists /* /redis-$VER
#...
CMD ["redis-server"]
构建:
$ doc ker build - t redis : lab - 3 .
查看大小:
doc kerinfo.net/2016/10/20161027203318.jpg" sizes="(max-width: 437px) 100vw, 437px" data-originalset="http://img.doc kerinfo.net/2016/10/20161027203318.jpg 437w, http://img.doc kerinfo.net/2016/10/20161027203318-300x117.jpg 300w" alt="20161027203318" width="437" height="170" data-tag="bdshare" />
哇!一下子减少了 50%,效果明显啊!这是最常用的一个精简手段了。
步骤 4:压缩你的镜像
方法:试着用命令或工具压缩你的镜像。
doc ker 自带的一些命令还能协助压缩镜像,比如 export 和 import
$ doc ker run - d redis : lab - 3
$ doc ker export 71b1c0ad0a2b | doc ker import - redis : lab - 4
但麻烦的是需要先将容器运行起来,而且这个过程中你会丢失镜像原有的一些信息,比如:导出端口,环境变量,默认指令。
所以一般通过命令行来精简镜像都是实验性的,那么这里再推荐一个小工具: doc ker-squash。用起来更简单方便,并且不会丢失原有镜像的自带信息。
下载安装:
https://github.com/jwilder/doc ker-squash#installation(复制此链接到浏览器打开)
压缩操作:
$ doc ker save redis : lab - 3 \
| sudo doc ker - squash - verbose - t redis : lab - 4 \
| doc ker load
注: 该工具在 Mac 下并不好使,请在 Linux 下使用
对比大小:
doc kerinfo.net/2016/10/20161027203328.jpg" sizes="(max-width: 435px) 100vw, 435px" data-originalset="http://img.doc kerinfo.net/2016/10/20161027203328.jpg 435w, http://img.doc kerinfo.net/2016/10/20161027203328-300x141.jpg 300w" alt="20161027203328" width="435" height="204" data-tag="bdshare" />
好吧,从这里看起来并没有太大作用,所以我只能说试着,而不要报太大期望。
总结
本期我们介绍了镜像层的知识,并且通过实验,介绍三种如何精简镜像的技巧(下期还有更强大的技巧)。这里主要介绍了三种精简方法:选用更精小的镜像,串联 Dockerfile 运行指令,以及试着压缩你的镜像。通过这几个技巧,已经可以将 300M 大小的镜像压缩到 150M,压缩率50%,效果还是不错。但这还远远不够,下篇我们将介绍一些终极手段,压缩效果可以达到 98%哦!