Docker从2013年开源,到目前已经经历了三年的不断完善与优化。2015年是Docker开源项目突飞猛进的一年, 一年里,Docker先后发布了v1.5、v1.6、v1.7、v1.8、 v1.9、5个大版以及7个修订版。

功能上增加了”只读容器”、”ulimit支持”、”日志驱动”、”Volume插件”、”网络插件”、”IPAM插件”等新特性,更加适合企业多样化的应用场景; user namespace的支持也合并进了1.9实验版,这使得Docker的安全性得到大大提升。

Docker registry 2(github上的distribution项目)的发布,让镜像更加标准化,镜像的传输更加高效; 新增了镜像签名验证机制,保证了镜像传输的安全。

Docker社区的活跃度也不断提升,Docker项目的社区代码贡献者由年初的900多增加到目前的1200多, 活跃的开源社区为Docker的稳定性和功能改进提供了有力的保障。同时,在6月份的DockerCon大会上, Docker公司与Linux基金会联合推出开放容器项目(OCP),微软,IBM,Google,Intel,Amazon等巨头的加入, 使Docker成为了容器技术的业界标准。也就是说容器本身的价值非常有限,重要的是容器的生态!

本文将从Docker的功能、稳定性以及代码质量方面对2015年Docker的进展情况进行总结。

功能进一步完善

只读容器

需求:为了方便项目迁移、升级和扩容,往往都需要制定一系列的标准和对数据日志数据的存储位置进行约束。

问题:开发团队并不是严格遵循制定的标准进行,把数据存放到了规定之外的路径下,导致数据丢失。 Docker引入的只读容器特性使容器的rootfs以只读方式挂载,这样运维人员可以强制规定日志或数据的存储路径。如果应用程序需要写数据,必须通过-v参数指定数据目录, 这样一来很好的起到了强制约束的作用。

另外的一个应用场景就是,如果基于Docker做PaaS平台,只读容器可能会优势更为明显。

ulimit支持

Linux的ulimit提供了一种简单的配额控制机制,但在Docker 1.6之前,一个Docker daemon管理的所有容器的ulimit是共享的, 使用起来很不灵活。Docker 1.6提供了基于容器的ulimit参数控制,用户可以为不同的容器设置不同的ulimit参数,使用起来更加灵活。

build过程的配置控制

问题:主机上已经跑了非常多的业务容器,现在要在这台主机上去执行构建镜像任务,导致资源紧缺,甚至影响业务运行镜像构建往往是一个非常消耗资源的操作,主机上还运行了很多线上业务,那么在构建镜像的时候很可能过度消耗系统资源而导致线上服务不稳定,所以即要保证构建任务顺利执行,更要保证线上业务稳定运行,Docker 1.6提供了对build过程的CPU、内存等资源进行配额控制的能力。

推荐:企业生产环境中,拿出几台机器专门做构建镜像的工作,高效并且安全!

日志驱动

问题:容器中推荐运行1个进程,如果运行了mysql,不安装syslog服务,收集日志怎么办?大家应该都很熟悉ELK,之前在虚拟机里安装syslog这种方法很奏效,但在容器这就行不通了,所以在v1.6中提供了可扩展的日志驱动接口,内置json-file和syslog两种日志驱动,用户可以根据需求把日志写入json文件或者发送到syslog(日志中心)这样就不用再为每个容器都安装syslog服务了。 基于日志驱动的go语言接口,在接下来的几个版中,逐步添加了fluentd, journald, awslog, gelf等日志驱动模块,满足用户各种复杂的日志记录与收集需求。

容器与镜像Label

问题:如果应用部署在单台主机上没有问题,如果想部署到多台主机上,如何调度呢?docker 官方自己做了一个项目叫Swarm,并且现在Swarm已宣布可以在生产环境中使用。为了方便Swarm之类的集群管理工具对主机进行分组管理,在v1.4中,用户可以为Docker Daemon指定一个或多个Label,满足应用部署调度到相对应的服务器上。 Docker 1.6新增了容器与镜像Label的支持,方便用户根据Label来对容器和镜像进行分组管理与过滤。

Volume插件

问题:容器删除后,容器里面的数据也会被删除掉。 为了确保删除容器数据不被删除,我们之前的做法就是通过-v把容器的数据目录和主机的目录做一个映射,但这样数据还是存放在本地磁盘中。在v1.7实验版引入了Volume插件机制,用户可以根据需要开发自己的Volume插件来使用外部存储服务。 比如:通过AWS EBS Volume插件,可以在创建容器时,自动创建一块EBS,把容器的数据保存在EBS上。 如果需要,用户也可以自己根据Volume插件的RPC接口规范开发适合自己的Volume插件,通过企业内部的NAS、SAN等存储服务来保存容器数据。 Volume插件在v1.8进入正式版对外发布,这样一来docker存储问题也就不难解决了。

Overlay网络

问题:单台主机容器之间通信没有问题,如果跨主机通信怎么办? docker容器ip不固定,以及跨主机互联一直是困扰Docker用户的一个问题,也是阻碍企业落地的一块绊脚石。 在Docker支持Overlay网络之前,常用的跨主机通信方案是通过在每台主机上运行个ambassador容器作为代理。这种方式无疑造成了管理成本的增加,并且也不适合用到生产环境。 Docker 1.9正式支持了基于VXLAN的Overlay网络,用户可以通过Overlay网络方便的实现容器跨主机通信,不过仅仅是解决了跨主机通信,并没有实现固定容器的IP功能。

网络插件

6月份之前,Docker默认提供了bridge(NAT)网络、Host网络、容器网络(与其它容器共享网络名空间)以及none(该模式下容器不创建网络设备,无法与外界通讯)五种网络模式。 虽然这几种网络模式能满足大多数应用场景的需求,但不够灵活,用户无法直接使用企业内部现有的SDN来为容器提供网络服务。

在1.7发布之际,Docker实验版引入网络插件功能。基于网络插件的RPC协议,用户可以开发自定义的网络插件来为容器提供网络服务。 比如:用户可以自己开发基于IPVLAN、MACVLAN、VXLAN等技术的网络插件实现跨主机通信。第三方提供的网络插件也如雨后春笋般出现, 如:支持多租户网络的Contiv 插件(https://github.com/contiv/netplugin),支持跨主机跨云通信的Weave网络插件等。网络插件在历经半年左右的打磨后,在1.9版本正式对外发布。

User Namespace

问题:容器和宿主机所使用的用户一样,容器安全吗? 容器安全是每个使用容器的技术人员都该考虑事情,Docker通过对Linux各种名空间的巧妙运用,实现了软件运行环境的沙箱,保证同一个主机上的不同进程之间的相互隔离。 但由于User Namespace的实现与libnetwork存在冲突,所以User Namespace的支持一直被搁置。很多使用容器的同学一直都还在担心容器的安全问题,但毫无疑问,User Namespace能大大提高Docker的安全性。在User Namespace支持之前,所有容器里的root用户其实与宿主机上的root用户是一样的,一旦容器沙箱被攻破(越狱),恶意用户就获取了宿主机的root权限,这样确实是很不安全。 通过User Namespace,可以把容器中的root用户映射到宿主机上的一个普通用户,这样即使发生越狱事件,攻击者获取的也只是宿主机上的一个普通用户的权限,现在是不是对容器更加有信心了?
User Namespace在经过7个月的讨论以及无数次修改与完善后,终于在1.9版发布之前,合并进了master(参考:https://github.com/docker/docker/pull/12648)。用户可以通过目前最新的实验版Docker体验User Namespace的相关功能。

稳定性持续改进

在2015年一年时间内,Docker团队与开源社区在Docker的稳定性提升方面做了大量工作。 最明显的表现是集成测试的覆盖面,在v1.4.0, 集成测试用例377个;到v1.9.1, 集成测试数量提升到1138个。 在每个PR提交以后,会自动通过github hook触发Jenkins来执行所有测试用例,从而尽可能保证整体功能的稳定性,docker在生产环境中运行1年多了很稳定。

代码结构逐步优化

Docker的一个竞争产品rkt(https://github.com/coreos/rkt)推出时,曾批评Docker的代码缺乏设计, 比较明显的表现是过多的嵌套调用(如:Docker 1.7之前的Job接口),不过最后rkt还是败给了docker。
2015年,Docker在代码结构上的重大调整主要包括:

1.Job接口的移除,减少了过多冗余的嵌套调用
2.网络相关的功能抽象到libnetwork项目独立维护
3.容器生命周期的核心库libcontainer由docker账号迁移到runc项目
4.支持Registry V2
5.本地镜像存储格式支持content addressability,镜像ID由随机生成改为按镜像内容计算(防止串改镜像内容)
6.API与Daemon功能的隔离,以及API路由的重新设计
7.镜像Builder的重构
8.Graph模块重构
9.移除LXC执行引擎,从而更加专注于native执行引擎的开发与维护

总结

在2015年,Docker逐步从一个实验品成长为一个羽翼丰满的可在生产环境使用的容器引擎。 Docker团队在开源方面的大力投入和活跃的开源社区,为Docker的成长提供了有力的保障。 以Swarm、Docker Compose、Kubernetes、Mesos为代表的容器管理与调度平台也如雨后春笋般出现, 为Docker在企业内部落地提供了便利。相信在不远的将来,容器技术将会在企业内部得到大范围的普及, 容器技术带来的运维管理、软件发行方面的变革也将对企业IT生产力产生巨大的提升。