文章目录

  • 背景
  • 前车之鉴
  • 经验分享
  • 善用docker commit
  • dev, release 协同打包
  • 多用ldd
  • 部分命令放到启动上
  • 字体缓存
  • python
  • 总结


背景

docker的部署是如何的方便也已经不用这里来阐述了把, 运维人员只要配好配置,一个load 一个run 就将应用起来了, 但是
存在一个问题, 有时候一不小心打出的镜像尽有好几个G, 发包难, 接收难。如何在打包的时候获得一个尽可能小的镜像呢?这就是这篇文章分享的一些点。

前车之鉴

关于如何减小docker 的体积, 通过网上搜索一些文章了解到一些方法,总结这些文章, 可行的方法大概有3种:

  • 多阶段构建
  • 使用小的基础镜像
  • 减少层级

经验分享

善用docker commit

docker 每次ADD COPY RUN 都会相应的增加一层,而这只能增加不能减少,dockerfile 多写一个ADD COPY RUN都会付出一定的体积代价。 但是每一次commit 也是增加一层,这样就带来了无限的可能性, 因此,可以下载一个alpha镜像,然后exec 进入容器内部, 根据应用要求逐步的构建出应用的基础镜像,最后在commit 并push 到仓库,以后构建该应用就可以用这个构建的基础镜像。

dev, release 协同打包

对于java 应用来说, 已经有很多的不错的基础镜像可以用了,但是对于一些可执行程序来说, 不仅的需要满足glibc的版本, 还需要满足它众多依赖的版本, 突然出现

/usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.19' not found (required by ./MonaServer)

这种报错该怎么办呢?
都知道,出现这种问题就需要对gcc进行升级, 但是基础镜像把这个升级一次就的需要大约1G 的大小,这个代价可是不少。
这里说的dev,release 打包方法就是启动2个基础镜像,其中dev 环境安装各种需要的开发环境(make 、cmake 、 gcc、 gcc-c++…),而release环境只是正常的基础镜像。在dev 和release的底层运行环境是一样的, 所以在dev环境下编译出的可执行文件迁移到release就不会出现上述的报错。

多用ldd

把上述的可执行文件在dev 环境下编译完也迁移到release 下, 但是往往会出现一些列的not found 报错, 迁移到release环境后对可执行程序以及以来so多进行ldd命令检测, 检测依赖的依赖是不是全, 如果不全的话直接从dev环境拷贝出来放入指定的目录并把该目录配置到环境变量LD_LIBRARY_PATH中。不建议放到/usr/lib64,/lib64这样的系统目录里,容易docker 起不来。

部分命令放到启动上

在执行python程序的时候会安装很多的库,而安装的过程中会生成很多的pyc文件, 这些文件完全可以放到运行的时候在生成,如果python有很多的依赖、很多的文件,这一步可以减少很多的体积!

字体缓存

有些应用需要在docker 里安装很多的文字, 这就需要执行
- mkfontscale
- mkfontdir
- fc-cache
如果在dockerfile 中直接RUN mkfontscale && mkfontdir && fc-cache会将这些字体的缓存也直接构建在docker 镜像中, 300字体会增加100M的体积, 因此可以借鉴上一步, 将这一步也放到CMD或者ENTRYPOINT上。

python

前几步介绍到python 的安装依赖可以放到运行步骤上,可以减少一些pyc文件的出现。但是还有一种更优的方法, 直接把python 通过pyinstaller 打包成一个可执行程序,这样就仅仅需要一个基础环境就可以运行程序了,不用在考虑python2 还是python3 也不需要考虑一大堆的依赖。一个alpha 足以。

总结

出发点只有一个, 减少docker的体积, 手段也只有一个:层尽量的少,无关内容尽量的少。