在畅聊Docker之前,我们先讲讲什么是容器?

现代软件开发的目标之一是应用程序既能运行在同一主机或集群上,又能彼此隔离,这样它们就不会过度干扰彼此的操作或维护,但由于要运行包、库和其他软件组件,这样就会变得会比较困难。

解决这个问题的方案之一是用虚拟机,它将相同硬件上的应用程序完全隔离,并将软件组件之间的冲突和硬件资源之间的竞争降到最低,但是虚拟机体积比较庞大,每个虚拟机都需要自己的操作系统,所以通常是GB大小而且很难维护和升级。

与虚拟机相反,容器将应用程序的执行环境彼此隔离,但共享底层OS内核。它们通常以兆字节为单位,使用的资源比虚拟机少得多,而且几乎是立即启动的。可以做到在相同的硬件上更密集地打包,而不需要花费太多的精力和开销。

容器提供了一种高效和高粒度的机制,将软件组件组合到现代企业所需的各种应用程序和服务堆栈中,并保持这些软件组件的更新和维护。

图片来源网络

Docker技术到底是啥?

Docker是一个开源项目,可以轻松创建容器和基于容器的应用程序,最初是为Linux构建的,现在也可以在Windows和MacOS上运行。

一直以来Docker都可以帮助开发人员快速构建轻量级和可移植的软件容器,从而简化应用程序开发、测试和部署等诸多环节。具体来说,它是一个用于构建应用程序的软件平台,可以提供一种小型和轻量级的执行环境用来共享操作系统内核,但在其他方面是独立运行的。

虽然容器概念已经出现不短的时间,但2013年推出的开源项目Docker在很大程度上帮助推广了这项技术,并推动了软件开发中容器化和微服务的趋势,这种趋势后来被称为云原生开发。

要理解Docker的工作原理,让我们看一下用于创建Docker容器化应用程序的一些组件。

图片来源网络

Dockerfile文件:每个Docker容器都从一个Dockerfile开始。Dockerfile是用易于理解的语法编写的文本文件,其中包含构建Docker镜像的指令,指定了容器的操作系统、编程语言、环境变量、文件位置、网络端口和其他组件,当然还指定了容器在运行后要做什么。

Docker镜像:编写好Dockerfile之后,就可以调用Docker构建工具build来创建一个Dockerfile镜像。

Dockerfile是一组说明如何生成镜像的指令,而Docker镜像是一个可移植文件,包含容器将运行哪些软件组件以及如何运行的规范,因为Dockerfile可能包含关于从在线资源库获取某些软件包的说明,所以需要注意指定正确的版本,否则Dockerfile可能会根据调用的时间不同生成不一致的镜像。但是一旦创建了一个镜像,它就是静态的。

Docker启动:Docker的实用程序run是启动容器的命令,每个容器都是一个镜像的实例。容器设计为瞬态和临时的,但是它们可以停止和重新启动。此外可以同时运行同一镜像的多个容器实例(每个容器具有唯一的名称)。

Docker Hub库:虽然构建容器很容易,但也不要以为需要从头构建每个镜像。Docker Hub是一个用于共享和管理容器的SaaS存储库,可以从中找到来自开源项目和软件供应商的官方Docker镜像,甚至普通公众的非官方镜像。甚至可以下载包含有用代码的容器镜像,或者上传自己的镜像共享它们,也可以将它们设置为私有,如果愿意还可以创建一个本地Docker注册表。

Docker 引擎:Docker引擎是Docker的核心,Docker创建和运行容器采用的是底层CS(客户端-服务器)技术。一般来说,当某人泛泛地说Docker,而不是指公司或整个项目时,他们指的是Docker引擎。Docker引擎有两个不同的版本:Docker Engine Enterprise和Docker Engine Community。

Docker在2017年发布了企业版Enterprise Edition,兼容最初的版本,仍然是免费开源的。除此之外,Enterprise Edition增加了高级管理功能,包括集群控制和镜像管理,以及漏洞监控,每个节点每年的成本为1500美元。

Docker组件、Docker集群和Kubernetes:Docker还使容器之间的协调变得更容易,通过将容器打包来构建应用程序堆栈。Docker组件简化了开发和测试多容器应用程序的过程。它是一个命令行工具,类似于Docker客户端,它接收一个特殊格式的描述符文件,用于从多个容器组装应用程序,并在单个主机上协同运行它们。

这些更高级的版本由其他产品提供,比如Docker Swarm和Kubernetes。但是Docker提供了基础。Swarm是从Docker项目中发展起来的,Kubernetes实际上已经成为Docker编配平台的首选。

Docker优势可圈可点

Docker容器提供了一种构建企业应用程序和业务流程应用程序的方法,这些应用程序比传统应用程序更容易安装、维护和移动。

Docker容器支持隔离:Docker容器使应用程序不仅彼此隔离,而且与底层系统隔离。这不仅使软件栈更干净,而且更容易使容器化应用程序使用系统资源,例如CPU、GPU、内存、I/O、网络等,它还可以确保数据和代码保持独立。

Docker容器支持可移植性:Docker容器在支持容器运行环境的任何机器上运行。应用程序不必绑定到主机操作系统,因此可以保持应用程序环境和底层操作环境的整洁和最小化。

例如,采用容器的MySQL将在大多数支持容器的Linux系统上运行,应用程序的所有依赖项通常都在同一个容器中提供。基于容器的应用程序可以轻易从on-prem系统迁移到云环境中,或从开发人员的笔记本电脑移到服务器上,只要目标系统支持Docker以及可能与之一起使用的任何第三方工具,比如Kubernetes。

通常,Docker容器镜像必须为特定的平台构建。例如Windows容器不能在Linux上运行,反之亦然;以前,绕过此限制的一种方法是启动运行所需操作系统实例的虚拟机,并在虚拟机中运行容器。

然而Docker团队后来设计了一个更优雅的解决方案,称为manifest,它允许多个操作系统的镜像并行打包。尽管manifest虽然还处于试验阶段,但这暗示了容器可能成为跨平台应用程序解决方案和跨环境应用程序解决方案。

Docker容器支持可组合性:大多数业务应用程序由几个独立的组件组成,web服务器、数据库和cache缓存。Docker容器可以将这些部件组合成一个容易更换的功能单元。每个部分由不同的容器提供,可以独立于其他容器进行维护、更新、交换和修改。

这本质上是应用程序设计的微服务模型。通过将应用程序功能划分为独立的、自包含的服务,微服务模型为过程缓慢的传统开发和单一僵化的应用程序提供了一种解决方案,轻量级和便携式容器使构建和维护基于微服务的应用程序变得更加容易。

Docker容器简化了编排和扩展:由于容器是轻量级的,并且开销很小,所以可以在给定的系统上启动更多的容器,而且容器也可以用于跨系统集群扩展应用程序,并将服务向上或向下扩展以满足高峰需求或节约资源。

用于部署、管理和扩展容器的大多数企业级工具版本都是通过第三方项目提供的。其中最主要的是谷歌的Kubernetes,这是一个支持容器部署和扩展的自动化系统,还支持容器连接、负载平衡和管理。Kubernetes还提供了创建和重用多容器应用程序或“Helm charts”图表的方法,这样就可以根据需要构建和管理复杂的应用程序堆栈。

Docker还内置了Swarm编排模式,目前该模式应用比较少,Kubernetes已成为某种默认选择。事实上Kubernetes与Docker Enterprise Edition捆绑在一起。

Docker是如何征服容器世界的?

几十年来,Unix操作系统(如BSD和Solaris)一直存在这样一种思想,即给定的进程可以在一定程度上独立于其操作环境运行。最初的Linux容器技术LXC是一种os级别的虚拟化方法,用于在一台主机上运行多个隔离的Linux系统。LXC是通过两个Linux特性实现的:命名空间(namespaces)和cgroups控制组(controlgroups),命名空间封装了一组系统资源,使其看起来像是专门用于该进程的;cgroups控制组用于管理一组进程的系统资源(如CPU和内存)的隔离和使用。

容器将应用程序与操作系统解耦,这意味着用户可以拥有一个干净且最小的Linux操作系统,并在一个或多个隔离的容器中运行其他所有东西。由于操作系统是从容器中抽象出来的,所以您可以将容器移动到支持容器运行环境的任何Linux服务器上。

Docker在LXC基础上进行了几项重大更改,使容器更加便捷和灵活。使用Docker容器,比使用虚拟机更快、更容易地部署、复制、移动和备份工作负载。Docker为任何能够运行容器的基础架构带来了云一样的灵活性。Docker的容器镜像工具也是LXC的一个改进,它允许开发人员构建镜像库,从多个镜像组合应用程序,并在本地或远程基础架构上启动这些容器和应用程序。

Docker表现并不万能

容器可以解决很多问题,但也不是万能药,有一些缺点是由设计本身造成的。

Docker容器不是虚拟机。人们对容器最常见的错误是将它们等同于虚拟机。然而,由于容器和虚拟机使用不同的隔离机制,它们有明显不同的优点和缺点。

虚拟机为进程提供了高度的隔离,因为它们在自己的操作系统实例中运行。该操作系统也不必与主机上运行的操作系统相同。Windows虚拟机可以在Linux管理程序上运行,反之亦然。

相反,容器使用主机操作系统资源的受控部分;许多应用程序以高度管理的方式共享相同的OS内核。因此,容器化应用程序不像虚拟机那样完全隔离,但是它们为绝大多数工作负载提供了足够的隔离。

Docker容器无法提供裸机速度。容器几乎没有虚拟机的开销,但是它们的性能影响仍然是存在的。如果您的工作负载需要裸机速度,那么容器可能足够接近—比vm更接近—但是您仍然会看到一些开销。

Docker容器是无状态和不可变的。容器从描述其内容的镜像启动和运行。默认情况下,该镜像是不可变的——一旦创建,它就不会更改。

因此,容器没有持久性。如果启动一个容器实例,然后将其终止并重新启动它,那么新的容器实例将不会具有与旧容器实例关联的任何有状态信息。

这是容器区别于虚拟机的另一个方式。默认情况下,虚拟机具有跨会话的持久性,因为它有自己的文件系统。对于容器来说,改变这种情况的唯一方法是创建一个新的、修改过的容器镜像。

从积极的方面看,容器的无状态性使容器的内容更加一致,它还迫使开发人员将应用程序数据与应用程序代码分开。如果希望容器具有任何持久性状态,则需要将该状态放置到其他位置。可以是数据库,也可以是在引导时连接到容器的独立数据卷。

Docker容器不是微服务。在前面提到过容器如何帮助创建微服务应用程序。这并不意味着将给定的应用程序粘贴到容器中就会自动创建一个微服务。无论微服务是否部署在容器中,都必须根据微服务设计模式构建微服务应用程序。

当虚拟机出现时,它们使应用程序与所运行的系统解耦成为可能。Docker容器进一步实现了这一想法,它不仅比虚拟机更轻量级、更便携、运行速度更快,而且还提供了虚拟机无法提供的扩展、组合和管理特性。

信息化和软件服务网 - 助力数字中国建设 | 责编:左右