从半年前开始,逐渐把新服务都放进了docker,使用也算有了一些心得,在这里总结一下。
入门
入门学习是看的这本书:Docker — 从入门到实践,感觉讲的还不错,都是些很实用的东西。
注意事项
Dockerfile的书写
可以遵循下面的几点规则
合理分层,重复利用镜像缓存
Dockerfile 中每一个指令都会建立一层:新建立一层,在其上执行这些命令,执行结束后,
commit
这一层的修改,构成新的镜像。创建了过多层的镜像是完全没有意义的,而且很多运行时不需要的东西,都被装进了镜像里,比如编译环境、更新的软件包等等。结果就是产生非常臃肿、非常多层的镜像,不仅仅增加了构建部署的时间,也很容易出错。这是很多初学 Docker 的人常犯的一个错误。
首先,如果所有的命令只有一个目的,那么就没有必要建立很多层,这只是一层的事情。因此,这里没有使用很多个
RUN
对一一对应不同的命令,而是仅仅使用一个RUN
指令,并使用&&
将各个所需命令串联起来。将之前的 7 层,简化为了 1 层。在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。删除当前层中创建的文件(注意只能删除当前层中创建的文件)
很多人初学 Docker 制作出了很臃肿的镜像的原因之一,就是忘记了每一层构建的最后一定要清理掉无关文件。我们可以在一组命令的最后添加清理工作的命令,删除为了编译构建所需要的软件,清理所有下载、展开的文件,并且清理
apt
缓存文件。这是很重要的一步,我们之前说过,镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。选择较小体积的基础镜像(比如 alpine)
使用私有仓库
对于公司来说有自己的私有仓库还是很有必要的,目前我们是用的是阿里云的私有仓库,这部分的使用直接看阿里云的文档即可。并且阿里云还提供个人专属的镜像加速器,这部分阿里云还是很良心的。
清楚废弃镜像
过多不再使用镜像会占用磁盘空间,所以我们需要去删除他们。这些镜像的特征就是标签为none,无标签镜像也被称为 虚悬镜像(dangling image) ,可以用下面的命令专门显示这类镜像:
1 | docker image ls -f dangling=true |
一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除。
1 | docker image prune |
如果这个命令不好使的话,我们还总结了三条命令:
1 | docker ps -a | grep "Exited" | awk '{print $1 }' | xargs docker stop |
这三句分别执行了如下的操作:
- 停止Exited状态的容器
- 删除Exited状态的容器
- 删除标签为
的镜像
有了这三板斧,基本就可以清除掉废弃的镜像了,我一般把他写在.bashrc里,然后在Jenkins的构建脚本里source .bashrc,来达到每次构建之前腾出一定空间的目的。
镜像备份
镜像的标签常用于对应该软件的各个版本。这个主要针对线上服务,测试环境不需要备份,只生成一个image打一个pub标签就够了,而线上服务通常生成一个image后打两个标签分别保存,一个打版本号标签,另一个打lastest标签,这样就做好了一次镜像的备份。
使用感受
部署和维护变得更简单
用docker最大的好处是你可以把你的应用以及应用运行依赖的环境和配置一起打包交付,做到开箱即用。并且环境还可以进行模块化,提高了复用性,不用每次部署新机器都到上面搞各种环境。整个领域的标准化和效率的提高。这里的部署还包括迁移,前段时间公司从青云迁移到了阿里云,公司的运维就很欢迎我用docker,因为这样对服务的部署和维护都有好处,Dockerfile减少了很多沟通成本,快速开/关机使维护变得简单。
隔离的环境
这一点知乎有个回答我觉得说的很清楚:
而对于我们来说,就是沙盒化使升级node版本不再是问题,运维给我们开一台服务器,我们就可以部署不同node版本的服务,并且服务之间做到了很好的隔离,不用担心操作一些内容干扰到另一些的运行。
总结
使用容器部署服务是未来趋势,并且现在在web服务的部署方面已经有了广泛的应用。而docker搭配go语言在分布式计算、大数据甚至机器学习领域的应用也都是令人期待的。