将Docker作为应用程序容器管理系统已经在最近两年当中成为众多开发人员及系统工程师们的标准实践方式。有一部分朋友甚至表示,容器方案是自OpenSSH之后最为可观且值得肯定的技术飞跃。Docker目前已经成为技术领域当之无愧的新生力量,且被广泛应用于各类云系统架构当中。然而除此之外,Docker还需要了解如何赢得开发人员们的芳心。
下面我们将一起了解Docker的发展历程,未来将要面对的竞争形势以及对发展前景的预估。
Docker是一款使用libcontainer的微容器管理工具。作为Solomon Hykes利用Go语言开发而成的项目,Docker于2013年转入开源并被快速应用在诸多领域当中。这款工具的出色灵活性甚至使其成为游戏规则的改变者。
在Docker出现之前,创建一套应用程序容器需要掌握多种相对比较先进的概念。LXC已经在这一领域占据了相当可观的市场份额,其卖点在于提供“纯虚拟化”解决方案并借此赚取利润。OpenVZ与Xen也在市场上拥有一定地位。不过这些系统在设计方面仍然很大程度上面向服务器解决方案,而且需要配合相当程度的配置工作。
这里我们要澄清一点:Docker的作用并不是取代LXC、OpenVZ或者Xen。它也并不是一套像KVM、VirtualBox以及VMware那样的虚拟化解决方案。Docker拥有属于自己的定位视角、独特的运作方式而且具备完全不同的功能出发点。
与OpenVZ、Xen以及LXC一样,Docker也采用rootfs原则——这实际上就是一套root文件系统。它采用树状结构作为远程系统的root(类似于chroot的作用),同时提供网络层与设置系统。但它同时也有着自己的一些独特设计。
首先,它的镜像与容器通过union mount文件系统(例如aufs以及devicemapper等)进行分层。这一方面节约了磁盘存储空间,另一方面也能够帮助我们在无需复制整套root的前提下快速构建容器环境。
另一大差异在于,Docker回避了访客系统当中的初始化步骤。换句话来说,容器的root只会被用作指定应用程序的运行环境。
最后,Docker拥有对镜像版本的注册与控制能力,这也正是其步入标准化的重要标志。在默认情况下,Docker会使用公共注册表。该注册表提供多套现成可用的镜像(既包括官方给出的正式镜像,亦拥有由社区用户提交的镜像),同时也为后续付费提供了实现空间。从理论层面讲,Docker在很大程度上与Git类似,而其Hub则类似于GitHub这样的服务方案。Docker同时采用多种常见概念,例如提交、标签以及远程注册服务器等等。
围绕Docker项目建立起的技术社区非常活跃,其中提供大量用于自动启动(fig,也就是现在的Docker Compose)、简化云集成及管理流程(CoreOS)以及实现监控任务(cAdvisor)的工具,而且这份工具清单还在不断拓展。
时至今日,Docker已经席卷了整个IT领域。OpenStack、Amazon、谷歌、CoreOS等等都在高度关注这项技术成果,甚至已经将其整合到了自己的基础设施当中。
不过激烈的市场竞争也即将到来!
Docker的主要诉求无疑在于简化容器创建流程,从而更为便捷地实现微服务架构管理。首先需要强调的是,容器本身其实是一种对应用程序进行完全隔离的手段。归功于其libcontainer库,Docker能够在整个cgroup管理流程当中始终实现内存与线程的彻底隔离。
除非使用者进行特殊指定,否则Docker不会开启主机设备上的任何一个端口。如果两套容器系统需要通过IP层进行通信,它们可以彼此连通,从而直接利用容器名称而非IP地址实现信息交互(因为IP地址可能随着容器重启而发生变化)。
Docker已经在云环境下获得极高人气,这主要是由于其极低的运行资源需求、出色的分卷管理以及能够显著降低磁盘存储空间需求的union mount文件系统。在研究Docker运作机制的过程当中,大家会发现我们能够非常轻松地利用它创建出一套具备可扩展性且/或高可用性的系统方案。
“docker”命令实际上是一种简单的REST客户端,旨在同daemon进行通信。在默认情况下,该服务(daemon)会创建一个unix socket(位置为/var/run/docker.sock)来提供该API。而“docker”命令将仅仅使用该API。
该API可以被用于监听各类事件,包括容器何时创建、启用或者停止。利用该API所提供的信息,大家能够轻松掌握哪套容器系统目前正在运行哪种服务并使用哪个端口等等。
如果大家不打算或者没有能力使用CoreOS、OpenStack等所要求的架构,那么也完全可以创建自己的架构及工具——而且整个过程并不困难。该API相当易于访问且效率极高。
下面请大家一起来看我们当前项目中的一个架构示例:
我们采取以下规划方式:
每台物理从服务器都配备有一项发现服务,用于监听该Dockers socket。
当某套容器系统启用或者停止时,该服务会将信息发送至主服务器。
该主服务器随后能够采纳适当的措施,例如修改nginx服务器配置或者删除/移除一台上流服务器等。
另一种选项则是对Docker的配置进行修改,从而保证该API能够在TCP模式下接受访问(即使其拥有网络可访问能力)。在这种特定情况下,小型客户端能够与所有从服务器相对接,并监听其中发生的全部事件。不过这种方式的基本原则仍然相同:每个事件都将允许管理员在nginx当中(假设使用nginx)对一台上游服务器进行添加或者删除。
二者的差别在于,这里主服务器必须处理全部指向所有从服务器的连接。而前一种方式的运行成本更低,因为所有从服务器都接入到主服务器中。
在这两类情况下,主服务器能够在每一套容器系统启用或者停止时得到通知,并可以修改主nginx服务器、重启容器或者规避事故发生。
当然,我们也可以同时设置两台主服务器来实现故障转移管理。这种解决方案完全可行而且易于维护。
毫无疑问,Docker非常适合系统管理员使用。但除此之外,它也能够在生产流程当中扮演重要角色,也就是面向开发人员。我们曾经为客户提供的一套解决方案就将Dockerfile与docker-compose文件结合在了一起(由Docker进行fig项目的检索)。
这一思路是首先定义开发人员的工作站在运行项目时需要哪些必备要素,而后创建Dockerfile(如果需要)以建立有针对性的镜像方案,同时将一个docker-compose.yml文件与这些容器相对接。
在此之后,当使用版本控制服务器(例如Git、Mercurial以及SVN等等)时,大家可以轻松设置该项目目录,从而将这些文件以及项目源代码添加到其中,并为容器指定所要使用的存储分卷。接下来,技术团队可以检索该项目,而且只需要使用“docker-compose up”这一条命令即可启用该服务。
让我们以一个Drupal项目为例,在这里我们要使用两套容器系统:
一套MySQL容器
一套包含有Apache加PHP模块的容器
Drupal的源代码被旋转在“/src”之下,并会被发送至Apache容器当中。而这也正是分卷的基本原则:主机上的一个本地目录或者文件可以被连接到特定目录下的一套或者多套容器处。在此之后,大家可以利用同样的方法处理MySQL存储目录,从而避免被保存在数据库内的记录发生丢失。
下面是Dockerfile内容示例:
FROM debian:7
MAINTAINER admin-dt@smile.fr
# Install software
RUN apt-get update && apt-get install apache2 php5 php5-mysql libapache2-mod-php5
# Start Apache
CMD /usr/sbin/apache2ctl -D FOREGROUND
接下来是docker-compose.yml文件内容示例:
web:
dockerfile: .
volumes:
- "./src:/var/www/drupal
ports:
- "8080:80"
links:
- "db"
db:
image: mysql
volumes:
- "./data:/var/lib/mysql"
其中“web”服务被链接至“db”中(参阅以上示例中的‘links’命令),因此它能够读取用于提供MySQL地址及端口(由Dockerfile负责提供)的各环境变量。
[page]
举例来说,以下变量皆可在“web”容器当中接受访问:
DB_PORT_3306_TCP_ADDR=172.17.1.24
DB_PORT_3306_TCP_PORT=3306
其它种种
大家当然也可以使用其它容器称,示例当中的“web”与“db”代表的是两套容器当中的设备名称。
换句话来说,“mysql://db”这一地址也可以变更。接下来,大家需要修改Drupal配置文件来访问该数据库,完成后工作到此结束。该项目将具备以下结构:
”data/”用于存储MySQL数据
”src/”用于容纳Drupal源代码
”Dockerfile”用于创建Apache/PHP镜像
”docker-compose.yml”用于描述容器的启动方式
为了保证示例的简单性,我们并没有提到Apache配置文件以及各容器如何共享各个分卷。总结来讲,就是这套Web服务器的配置可以随意进行修改。
大家可能还注意到,绑定的端口也已经得到处理。由于开发人员用不着获得使用端口80的权限,因此我们利用本地端口8080来映射Apache容器的端口80。开发人员只需要访问127.0.0.1:8080即可查看当前处于运作状态的Drupal实例。
为了理解这套对接体系,请大家参阅以下图表。
就目前的形势看,Docker似乎成了世界上惟一一项沐浴在赞美当中的容器技术成果。然而请记住,Docker使用libcontainer与cgroups,这意味着为了能够使用这些内核的功能,该服务必须以root方式运行。而这很可能招致安全问题。
这实际正是CoreOS以及其它同类方案批评Docker的主要着眼点——但值得一提的是,这项技术确实极具吸引力,也支撑着CoreOS创建出了当下最具知名度的云系统方案之一。Docker需要root权限来接入cgroups,但以root角色运行的服务确实很可能给系统造成安全漏洞。
Docker的开发团队就此给出过礼貌的回应。很明显,他们将在未来的版本升级当中考虑这一问题,而且欢迎大家提出任何能够解决这些缺陷的建议(不过迄今为止,Docker还没真正惹出过任何麻烦)。不过各位读者朋友别慌:这项漏洞被真正利用的可能性非常之低。截至目前,惟一一次安全问题出现在2014年的1.0版本当中,而且现在问题已经得到解决。
总而言之,CoreOS决定创建自己的一套容器系统(能够使用Docker镜像),名为Rkt(发音同火箭,即‘rocket’)。但就目前的情况看,大多数用户将继续在CoreOS解决方案的基础之上使用Docker。就在Rkt刚刚发布之时,LinuxContainers(LXC背后的大型项目)亦宣称计划与Cannonical公司合作开发LXD。
如大家所见,容器管理领域的一举一动都在尽可能向内核靠拢,而由此带来的结果就是其性能水平将不断提升。
时间逐渐推移,容器的必要性也变得愈发凸显。
但Windows与OS X又会如何?对于OS X来说,目前还没有相关声明出炉,更不存在任何产品可供选择。因此,使用boot2docker(一套专门用于运行Docker的虚拟机)也就成了惟一的出路。Windows目前同样需要依赖于boot2docker,不过微软公司最近在声明中指出,未来的微软操作系统将直接纳入容器机制。具体如何,我们将拭目以待……
很明显,Docker是一项适用于开发及系统管理工作的技术成果。它能够不断提供精简效果并改善性能水平,同时具备良好的可行性,这一切使得用户能够以前所未有的方式轻松建立服务。无论您的基础设施到底处于何种规模,相信Docker都能助大家一臂之力。
除此之外,它的亮点也完全能够体现在生产流程当中。如今开发工作正变得日趋标准化,而开发人员与系统之间的界线也变得越来越精细。我们期待着Docker下个版本的正式降临,希望到时候它能够提供更具吸引力的竞争优势。
就目前来看,Docker仍然是容器领域的惟一王者。
原文标题:How to get systems administrators and developers to agree with Docker