使用Docker容器——轻量灵活的VM同类,来接管“依赖地狱”。学习Docker是如何基于LXC技术,通过把应用包装在容器里来使应用具有移植性和独立性。
想象一下可以轻松地把应用和它的依赖打包,然后在其他的开发、测试和生产环境上平滑的运行。这就是开源Docker项目的目标。尽管它现在还没正式到生产阶段,最新的发布(本篇文章编写时是0.7.x)使得Docker实现这一伟大目标又近了一步。 Docker容器试图解决“依赖地狱”问题。现代的应用通常从已存在的组件组合而来,并且依赖其他服务和应用。比如,你的Python应用可能使用Postgre所为一个数据存储,用Redis缓存以及使用Apache作web服务器。每个这些组件都附带自身的一些依赖,这些依赖可能与其他组件产生冲突。通过打包每个组件及其依赖,Docker容器解决以下问题:
Docker容器:一点背景2013年初,Docker在dotCloud—一个平台即服务的、以云计算为中心的公司,以一个开源项目的形式诞生。Docker是该公司已经开发的用来在数千台服务器上运行云业务的一个自然扩展技术。它是用Go语言编写的,Go语言是由谷歌开发的一种基于C语言且语法松散的静态类型编程语言。快速发展了6到9个月,这家公司聘请了一个新的CEO,加入了Linux基金会,将公司名改为Docker,并且宣布将工作重心转移到Docker容器及其生态系统的开发。作为Docker容器的受欢迎程度进一步说明,在写这篇文章的时候,它已经在GitHub上被 Star 8985次并 Fork1304次。图1表明了Docker容器在谷歌搜索持续上升的受欢迎度。随着Docker公司发布了第一个版本容器的产品部署以及广泛的社区知道了Docker容器的有用性,预计过去12个月的波形图将会在未来12个月内相形见绌。
图1. 过去12个月Docker软件在谷歌搜索上的趋势图 在引擎罩下Docker运用了一些强大的内核级技术并让我们触手可及。容器虚拟化的概念早在几年前已经出现,但通过提供一个简单的工具集和统一的API接口管理一些内核级技术,如LXCs(Linux容器)、cgroups和一个写复制文件系统,Docker已经创建了一个比其各部件更好的工具。它就是一个潜在的用于开发运营商、系统管理员和开发者的规则转换器。
Docker提供工具使得利用容器创建和操作尽可能简单,容器沙箱相互处理。你可以暂时把一个容器当成一个轻量级的虚拟机。 Linux容器和LXC,一个用于Linux容器的用户空间控制程序包,是组成Docker的核心,LXC使用内核级命名空间将主机和容器相互隔离。用户命名空间将主机和容器的用户数据库分离,这样保证了容器的root用户没有主机的root权限。程序命名空间仅负责显示和管理程序在容器中,而非在主机运行。而且网络命名空间提供自己的网络设备和虚拟IP地址给容器。
LXC提供的另一个组件是控制组(cgroups)。命名空间负责主机与容器之间的隔离,而控制组实现资源核算和限制。当允许Docker限制被一个容器消耗的资源:如内存、磁盘空间和输入输出时,控制组也会输出大量与之相关的指标。这些指标使Docker能够监控容器内各个进程的资源消耗并确保每个进程只获取可用的公平共享资源。 除了以上组件,Docker一直在用AuFS(高级多层次统一文件系统)作为容器的文件系统。AuFS是一个能透明覆盖一或多个现有文件系统的层状文件系统。当一个进程需要修改一个文件时,AuFS创建该文件的一个副本。AuFS可以把多层合并成文件系统的单层表示。这个过程称为写复制。
真正酷毙的是,AuFS允许Docker把某些镜像作为容器的基础。例如,你可能有一个可以作为很多不同容器的基础的CentOS系统镜像。多亏AuFS,只要一个CentOS镜像的副本就够了,这样既节省了存储和内存,也保证更快速的容器部署。 使用AuFS的另一个好处是Docker的版本容器镜像能力。每个新版本都是一个与之前版本的简单差异改动,有效地保持镜像文件最小化。但,这也意味着你总是要有一个记录该容器从一个版本到另一个版本改动的审计跟踪。 传统上,Docker依赖AuFS提供了写复制存储机制。然而,最近添加的一个存储启动API可能降低这种依赖。最初,可用的存储驱动有三种:AuFS、VFS和设备映射器-与红帽合作的产物。
自版本0.7起,Docker就与所有Linux发行版协作。然而,它并没有兼顾大部分非Linux系统,如Windows和OS X。在那些操作系统上使用Docker的推荐方式是,用Vagrant在VirtualBox上提供一个虚拟机。 容器VS.其他虚拟化类型那容器到底什么是以及它与基于管理程序的虚拟化的区别是什么?简单地说,容器在操作系统层面虚拟化,而基于管理程序的虚拟化在硬件层面。效果类似,但区别很重要,这也是我花了点时间探索它们的差异和由其产生的差异和权衡的原因。 虚拟化: 容器和虚拟机(VMs)都是虚拟化工具。在虚拟机上,一个管理程序使各个孤立的硬件可用。通常,这包括两种类型的管理程序:类型1直接运行在硬件裸金属片上,而类型2则在客户操作系统上作为软件附加层运行。开源的Xen和VMware的ESX是类型1 的例子,类型2的实例包括Oracle的开源VirtualBox和VMware服务器。虽然相比Docker容器而言,类型1是个更好的候选,但我在文章的其他部分并不区分这两种类型。
与此相反,容器构造操作系统中可用的受保护部分-它们有效地虚拟化操作系统。运行在同一个操作系统上的两个容器不知道它们在共享资源,因为彼此拥有自己的抽象网络层和进程等等。 操作系统和资源由于基于hypervisor的虚拟化仅仅提供了对硬件的访问,因此你还需要安装操作系统。这样就会运行多个完整的操作系统,每个虚拟机上运行一个,这将快速地吃完服务器上的诸如内存(RAM)、CPU和带宽等资源。
容器运行在操作系统之上,把正在运行的操作系统当作自己的主机环境。它只运行在这样的空间上:这些空间是主机操作系统的一部分,而且各个容器使用的空间相互独立。这会带来两个非常鲜明的优点。第一个优点是更高效的使用资源。如果一个容器不执行任何操作,那么它就不会耗尽资源,而且容器可以调用自己所在的主机操作系统以实现其所需要的部分或者全部功能。第二个优点是容器成本低,因此可以快速地创建和删除容器。容器不需要对整个操作系统进行重启或者关闭。容器仅仅需要的终止运行在自身独立空间的进程。因此启动和停止容器更像是启动和退出某个应用,因此启动和停止就非常快。 图2展示了两种类型的虚拟机和容器
图2.虚拟机和容器 独立的性能和安全
Docker容器里所执行的进程与宿主机操作系统上运行的进程或者运行在其它Docker容器里的进程是相互独立的。不过,所有的进程都是运行在相同的内核里。Docker使用LXC来给每个容器提供独立的命名空间,内核里的这项技术已经具有5年多的历史了,已经十分成熟。另外,容器还使用了控制组,Linux内核里的这项技术比LXC的历史更长,它对资源进行审核和限制。 Docker服务进程本身还是一个潜在的攻击载体,这是因为它目前只能以root权限运行。对LXC和Docker的改进都应当允许以非root权限运行容器,而且可以用另外一个用户运行Docker服务进程。
虽然容器所使用的这种类型的隔离总的来说非常强大,然而是不是像运行在hypervisor上的虚拟机那么强壮仍具有争议性。如果内核停止,那么所有的容器就会停止运行。虚拟机具有优势的领域是它十分成熟,而且广泛的应用在生产环境中。相比之下,Docker和它的支撑技术几乎没有任何行动。特别是Docker每天都进行大量的修改变化,而且我们大家都知道变化是安全的天敌. Docker和虚拟机-亦敌亦友上面我们一直在对Docker和虚拟机进行比较,现在该看看这两种技术彼此在哪些方面是真正互补的。Docker在虚拟化的环境下运行的非常好。很显然,你不需要对各个虚拟主机的每个应用或者组件进行封装。而且假定给你一台Linux虚拟机,你就能够很容易地部署上Docker容器。这也就是在非Linux系统,比如OS X和Windows上运行Docker的官方安装方式是在Vagrant的协助下安装基于Ubuntu虚拟机的Precise64不让你感到吃惊的原因所在。http://www.docker.io站点有详细并且简单的指令。
首先,虚拟化和容器在某些方面表现的非常相似。一开始,这让你觉得容器就是非常轻量的虚拟机。然而,随着你对容器的认识,你对容器的理解就会有微妙的并且是重大的不同。Docker在容器最擅长的领域即轻量级应用的打包和部署方面都能充分发挥容器的长处。 |