Docker生态系统系列之二:容器化综述


【编者的话】本篇文章是介绍Docker生态系统的第二篇,该文章首先简要介绍了Linux容器化的历史,然后介绍容器化的优点,再讨论Dockerfile的优点,最后讨论了容器化应用的架构。

应用的迁移部署是一件非常复杂的事情。我们不仅要针对每个环境单独调整,可能还会面临其它的问题,比如检查依赖、扩展应用、在不影响整体应用的情况下单独更新组件。

Docker容器化的思想和面向服务式的设计模式试图解决这些问题。应用程序可以拆分为可管理的且按功能划分的组件,组件可以单独打包它们所需要的全部依赖,这样,应用程序可以非常容易的部署在任何架构中,扩展和更新组件也非常容易。

在这个指南中,我们将讨论容器化的好处以及Docker是如何帮助我们解决前面提到的问题的。Docker是分布式容器部署的核心组件,它易于扩展和管理。

Linux容器化的简要历史回顾

容器化和隔离化在云计算领域并不是新概念。许多Unix系的操作系统早就实现了容器化技术。

2008年,LXC被添加到了系统内核中,它的编译模块成为了后续容器化技术的基础。LXC综合了内核cgroups(隔离和跟踪资源的使用)和命名空间(使组与组之间被隔离)来实现轻量级的进程隔离。

后来,Docker就出现了,它是一个简化创建和管理容器的工具。它最初使用LXC作为默认的执行驱动(而现在,这个模块已经被开发成了一个工具包libcontainer)。虽然Docker没有引入什么新的思想,但之所以它被程序员和系统管理员所钟爱,是因为它简化了这个过程并标准化了接口。Docker在Linux程序员中再次激起了一个容器化的兴趣热潮。

虽然在本篇中我们会泛泛的讨论几个容器化的话题,但是由于其超高的人气和标准化的适用,我们将重点讨论Docker容器化。

容器化可以给我们带来什么?

容器化给程序员、系统管理员和系统维护团队带来了很多的好处。接下来我将逐个介绍。

对容器化应用的宿主机抽象化

容器是完全标准化的。这就是说容器与宿主机、与外界的一切通信交互都使用预定义的接口。一个容器化的应用不依赖也不需要关心宿主机资源或者架构的细节,这就简化了部署时应用对操作系统的要求。同样,对于宿主机来说每一个容器都是个黑盒子,它也不需要关心容器内部的细节。

容易扩展

宿主机与容器间的虚拟化带来的好处之一就是:对于一个既定的应用,可以简单而直接的扩展。容器化的应用结合面向服务的设计奠定了易扩展性的基础。

当系统处于筹备阶段或者测试环境中时,程序员可在他们的开发机上部署多个容器。而当容器进入生产环境时,它们将再次被扩展。

简单的依赖管理和应用版本控制

容器可以让程序员将一个应用或者应用组件与它们的依赖打包成一个单元。宿主机不需要去关心某一个容器运行所需要的依赖。只要它可以运行Docker,那么它就可以运行所有的Docker容器。

这同样可以简化依赖管理和版本控制。宿主机和开发团队不再需要负责应用程序的依赖库管理,因为除了依赖相关的容器,它们都应该在容器内部。

轻量级的隔离的运行环境

虽然容器不提供相同级别的隔离和资源管理虚拟化技术,但是这个折中却带来了其它优势:轻量的运行环境。容器从进程级别隔离,且共享着同一个内核。这就是说容器内并没有一个完整的操作系统,它可以瞬间启动。开发者可以在开发机上无差别的启动几百个容器。

层共享

“容器是轻量化的”还可以从另一个角度理解,它们是由层组成的。如果多个容器都基于同一个层,那么他们就可以共享底层,而不会重复,这使得后续的镜像占用硬盘空间达到最小。

可组合型和可预测性

Docker文件支持用户自定义创建镜像时的具体操作。这就允许你去定制自己的运行环境,如果需要的话还可以保存在版本控制系统里。在同样环境下,同样的Docker文件编译出的容器镜像是高度一致的。

用Dockerfile来实现可复现和一致构建

当使用交互式的操作来创建容器镜像时,我们应该及时把确定的操作加入到配置步骤中。Dockerfile是一个简单的配置文件,它描述了如何从一个已知起点开始构建镜像。

Dockerfile非常实用,并且容易掌握,它有以下几个优点:
  • 易于版本控制:Dockerfile文件可以提交到一个版本控制软件中来追踪变更和复现任何错误。
  • 可预测性:基于Dockerfile构建镜像可以从镜像创建的环节来避免操作上的错误。
  • 问责制:如果要分享你的镜像,最好的办法是提供Dockerfile,这样别人可以创建这个镜像并审阅这个过程。Dockerfile提供了创建这个镜像的历史操作步骤。
  • 灵活性:基于Dockerfile来创建镜像,可以覆盖原有的默认的构建配置。也就是说在构建或者运行时你不需要再输入那些复杂的命令行参数。


在实现可重复的自动化构建容器方面,Dockerfile是一个非常好的工具。

容器化应用的架构

如果要将应用部署到容器中,首先需要考虑应用的架构。一般来说,最好使用面向服务的架构。

通常在用Docker来设计应用或者服务时,最好的方法是打破面向服务架构的设计,而采用独立容器的设计。Docker技术本身也倾向于这种设计,因为以后可以容易的扩展或者独立升级组件。

实现这种设计的应用应该具有以下几个特点:
  • 它们不应该依赖或者关心宿主机上的任何细节。
  • 每一个组件应该提供一致性的接口,使得调用者可以访问服务。
  • 每一个服务应该在初始化阶段从环境变量中获取参数。
  • 应用产生的数据应该通过Volumes存储在容器外部或者数据容器中。


只要接口不变,这些策略使得组件可以被独立的更换或者升级。这使得它们向着水平扩展的方向发展,也就是根据瓶颈情况,每一个组件都可以扩展。

每一个组件通常都有定义合理的参数默认值,而不是强制编码它们。组件可以使用这些值作为候选值,但最好是从运行环境中获取这些值。这通常需要借助于服务发现工具,使得组件可以在启动过程中去查询这些参数。

将配置文件放在实际容器的外面,就可以在不需要重新构建镜像的情况下简单的改变应用的行为。这样可以使得一个配置可以影响同一组件的不同实例。通常来说,面向服务的设计与运行环境配置策略配合的比较好,这是因为二者都需要更灵活的部署和更直接的扩展。

用Docker Registry管理容器

一旦应用被切分为功能组件,并在容器中部署,那下一步通常是确保你的容器可以通过Registry获取。将容器镜像上传到Registry,紧接着Docker宿主机可以通过简单的已知名称来拉取容器并启动其实例。

满足这个要求的Docker Registry有很多。有一些是对外公开的,任何人都可以查看和使用已经被提交的镜像,相对的也有些是私人的Registry。镜像可以用标签来标识,以方便准确的获取或更新。

总结

Docker提供了分布式容器部署的基础构建模块。通过将应用打包到它们各自的容器中,水平扩展变成了简单的启动或者关闭每个组件实例群的过程。Docker不仅提供了创建镜像的必需工具,也提供了方便新用户或宿主机管理和分享镜像的工具。

尽管容器化应用提供了必要的隔离和打包来协助部署过程,还是需要一些在分布式集群或者宿主机上管理和批量化容器的工具。在下一个教程中,我们将讨论服务发现和全局配置存储如何协助集群容器部署。

本系列的其它文章

Docker已经为开发者和管理员提供一个简单的平台来创建和部署可扩展的应用。在这个系列中,我们将探索Docker如何与其他组件整合在一起,并用它们提供的工具集来便捷地提供高可用性的分布式系统。
  1. 常用组件介绍(已翻译)
  2. 容器化的综述(本文)
  3. 服务发现和分布式配置存储(已翻译)
  4. 网络与通信(翻译完毕)
  5. 调度与编排(翻译完毕)


原文链接:The Docker Ecosystem: An Overview of Containerization (译者:陈杰 校对:李颖杰)

===============================================
译者介绍
陈杰,北京理工大学计算机学院在读博士,研究方向是自然语言处理在企业网络信誉评价方面的应用,平时也乐于去实现一些突发的想法。在疲于配置系统环境时发现了Docker,跟大家一起学习、使用和研究Docker。

2 个评论

"通常在用Docker来设计应用或者服务时,最好的方法是打破面向服务架构的设计,而采用独立容器的设计。"
这句翻译错了吧,翻译成完全相反的意思了。原文“Service-oriented applications break the functionality of a system into discrete components that communicate with each other over well-defined interfaces”应该是基于服务的应用将系统的功能分解成独立的组件,通过定义良好的接口进行通信。
感谢指出。这个 “将系统的功能分解成独立的组件” 与 “采用独立容器的设计” 意思差不多,我没有严格逐字翻译,加入了一点自己的理解。再讨论下吧~

要回复文章请先登录注册