原文链接
Docker,好处都有啥,谁说对了就给他!
随着Docker的登场,Web应用的服务端开发发生了翻天覆地的变化。感谢Docker,现在基于微服务开发可伸缩,可管理的应用程序变得更为简单。为了帮助理解什么是微服务以及Docker起的什么作用,让我们举一个差不多真实的例子。
假设在你的Web开发团队中有一个John Doe,他使用的是Mac,他的同事Jane Doe,使用的是Windows。最后,还有一个Jason Doe,你们团队的第三名成员,决定他要在Debian上工作。难以置信,这三名开发者使用不同的环境来开发同一款应用,并且每个环境都需要他们各自的设置。每个开发者查阅20页的说明书来安装不同的库,以及编程语言,让一切都运行起来。在不同的环境中,这些库和语言不可避免的会有所冲突。再增加三个环境——准备,测试以及生产服务器。然后你会发现要在开发,测试以及生产环境中保持一致是多么的困难。
我们上面所描述的问题与开发一体化应用相关。然而如果我们决定顺应现代潮流并开发基于微服务的应用,情况会变得更糟。因为微服务是自包含的,独立的应用单元,每一个实现一个特定的业务功能,它们本身可以被视为小型应用程序。如果你为你的应用创建一打微服务会怎么样呢?如果你决定使用不同的技术栈来建立微服务又会怎么样呢?你的团队很快就会陷入麻烦,因为他们要管理比传统一体化应用还要多的环境。
有一个解决方案:使用微服务并使用容器封装每个微服务。Docker帮助你管理这些容器。
Docker就是一个容器化的工具,最初建立在Linux容器上,提供了处理容器化应用的简单方式。接下来我们看看Docker的优势以及它在实现微服务中起到的作用。
容器化——虚拟化的一个选项,拥有着改变我们开发应用方式的潜力。Docekr作为容器化的工具,经常被拿来与虚拟机比较。
引进虚拟机是为了优化计算机资源的使用。可以在一个服务器上运行多个虚拟机,并在每个虚拟机上部署一个应用。以这种模式,虚拟机为每一个应用实例提供了一个稳定的环境。不幸的是,当我们缩放我们的应用时,我们很快就会遇到性能问题,因为虚拟机消耗许多资源。
上面的图展示的是使用管理程序在一个服务器上运行多个操作系统。管理程序减少了运行多个操作系统所需的资源。
由于微服务与小型应用类似,必须将微服务部署到它们自己的虚拟机实例中以确保独立的环境。可以想见,一个虚拟机只部署一个应用的一小部分不是最有效的选择。使用Docekr,能够减少性能开销,并在一个服务器上部署上千个微服务,因为Docker比虚拟机需要的计算资源更少。
至此,我们讨论了为一个应用程序管理环境。现在假设我们正在开发两个不同的项目,或者你需要测试一个应用的两个不同版本。此时,app版本或库之间的冲突是不可避免的,在同一个虚拟机中支持两种环境实在令人头痛。
与虚拟机的工作方式不同,在Docker中,不需要为了避免冲突而不断建立新的环境。我们知道在Docker中没有冲突。Docker保证应用程序的微服务会在它们自己的环境中运行,这个环境完全独立于操作系统。
感谢Docker,不需要每个开发者都仔细阅读20页的说明书。由一个开发者建立一个包含必要库和语言的稳定环境,并将设置保存到Docker Hub中。然后,其他的开发者只需要下载设置就能拥有完全相同的环境。Docker为我们节省了大量时间。
Google一下你就能发现使用Docker的其他好处,例如更快的开发速度,技术栈的自由选择等。但是,不得不说这些人们所谈论的其他好处事实上与Docker本身无关。是基于微服务的架构使你更快开发新特性并选择你喜欢的技术栈。
Docker的优势总结如下:
现在,让我们看看Docker的架构,搞清楚它究竟是怎样帮我们开发基于微服务的应用的。
为了更好地理解Docker是怎样工作的以及如何使用Docker,我们会以一个非常简单的微服务为例。有许多微服务架构的示例,但是这里我们建一个我们自己的微服务以更好地契合我们的主题。
上图中的应用仅包含了三个服务,并实现了一个博客网站。(这个应用的例子在 GitHub 上。)每个服务——Nginx(web服务器),MySQL(数据库),以及Wordpress(博客引擎)——都封装在一个容器中。
上面的例子并不包含完整的Docekr架构,因为容器只是架构的一部分。Docker架构包含三个主要组件——镜像,容器以及登记中心。我们会逐一看一下三个组件。不过,在你使用Docker开发之前,需要先安装 Docker 。
为了让Docker容器一起运行,首先需要在docker-compose文件中注册它们,Docker Compose负责协调所有服务。
首先说明一下docker-compose.yml文件。
version: '2' services: nginx: build: nginx restart: always volumes_from: - wordpress wordpress: image: wordpress:php7.1-fpm environment: WORDPRESS_DB_HOST: mysql WORDPRESS_DB_PASSWORD: example depends_on: - mysql mysql: image: mariadb environment: MYSQL_ROOT_PASSWORD: example volumes: - ./demo-db:/var/lib/mysql 复制代码
我们必须关注这个文件的三个元素。首先,必须指定服务——"nginx","wordpress"以及"mysql"。其次,必须指明镜像——注意服务下面的"image"属性。最后,必须指定"volumes"属性。
Docker容器并不是凭空产生的。它们由Docker镜像实例化而来,镜像就像是容器的蓝图一样,是Docker架构的第二组件。要运行Docker镜像,必须使用Dockerfiles。
Dockerfiles就是一些文本文件,描述了如何创建镜像。还记得在docker-compose中,我们没有为Nginx指定一个镜像吗?我们不想简单地使用一个已经准备好的Nginx镜像,因此我们使用"build"。这样,我们告诉Docker去生成Nginx镜像并应用我们自己的配置,并且使用Dockerfiles告诉Docker,使用哪个镜像,使用哪些配置。
在我们的应用中,有个Nginx Dockerfiles的例子:
FROM nginx:alpine COPY site.conf /etc/nginx/conf.d/default.conf 复制代码
可以看见,只给出了两条说明,第一条指出创建容器的基础镜像,在我们的例子中,Nginx容器的基础镜像就是“nginx:alpine”。可以使用特定版本的库或语言来创建镜像。第二条告诉Docker去哪里找配置文件。通常将这些文件放在Dockerfile同一目录下。
有一个重要的细节:一旦登记了一个镜像,Docker镜像就不能改变。我们只能从Docker Hub中拉一个镜像,修改它,然后再推一个新的版本。每个新容器都会从docker-compose.yml或Dockerfile中指定的基础镜像实例化。由于Docker从操作系统中隐藏了容器环境,因此你可以使用特定版本的库或编程语言而不会与系统中的版本冲突。
在docker-compose文件中,每个服务都有一个叫做"volumes"的属性。在Docker中,"volumes"是处理持久化数据的手段。不同的容器可以访问同一个"volumes",在docker-compose文件中,对于Nginx服务,我们使用属性"volumes_from",告诉Nginx容器,它必须访问WordPress volumes。
当位于不同服务器上的多个容器需要访问相同的数据时,可以共享volumes。这就是使用"volumes_from"的原因。Docker会为我们管理volumes。
至此,我们已经讨论了镜像与容器——Docker架构的两个基本组件。但是你可能想问这些镜像都在哪里呢?在我们的示例应用中,所有的容器都来自Docker Hub的标准镜像。这是 Nginx , Wordpress , MySQL 的基础镜像链接。
登记中心是Docker生态的另一个组件,Docker Hub是关于登记中心的一个很好的例子。登记中心就是镜像存储的库。我们可以从登记中心中推拉镜像,为一个项目建立我们自己的登记中心,并使用登记中心中的镜像建立我们自己的基础镜像。
现在,我们已经讨论了全部三个组件——容器,镜像以及登记中心。Docker架构还包括其他重要组件——命名空间,控制组以及联合文件系统(UnionFS)。命名空间让我们使容器彼此分隔,他们无法访问彼此的状态,控制组是在容器中管理硬件资源的必要条件,联合文件系统为容器创建构建块。
这些额外的组件并不是真正由Docker建立。在Docker之前,它们就已经在Linux容器中可用。Docker只是在容器管理中使用了相同的理念。
我们已经讲述了许多新的概念,让我们来总结一下:
在示例中提供的应用程序可以轻易地使用其他服务扩展。假设我们想缓存响应。建立一个叫Varnish的服务,Varnish帮助我们缓存经常请求的HTML页面,图片,CSS以及JavaScript文件。更新后的应用看起来就像这样:
下面是添加了Varnish服务的Docker Compose文件:
version: '2' services: varnish: build: varnish ports: - 80:80 depends_on: - nginx nginx: build: nginx restart: always volumes_from: - wordpress wordpress: image: wordpress:php7.1-fpm environment: WORDPRESS_DB_HOST: mysql WORDPRESS_DB_PASSWORD: example depends_on: - mysql mysql: image: mariadb environment: MYSQL_ROOT_PASSWORD: example volumes: - ./demo-db:/var/lib/mysql 复制代码
需要在docker-compose.yml文件中添加一个服务,配置并指定端口。如果你不想用Varnish了,直接从docker-compose中移除并更新配置。可以查看GitHub上的 simple WordPress containe 项目。
这几乎就是关于使用Docker管理容器我们所需要了解的一切了。不过,仍然有一件事在困扰我,我们如何管理那么多服务器上的成千上万个Docker容器呢?最后一小节将回答这个问题。
Docker允许我们在一个主机上一个一个地部署微服务。一个小的应用都有着许多服务,当你的应用增大时,更是不计其数。如果你运行着多个服务器,怎样将那么多容器部署到服务器上呢?如何控制它们的规模呢?Docke生态中包含了容器协调系统来解决这些问题。
容器协调系统是一个额外的工具。知道2016年年中,Docker还没有提供一个管理成千上万微服务的方式。但是现在,有了Docker Swarm,一个内建的容器协调框架。
Docker现在出现了一个特殊的模式——swarm模式——可以用来管理容器集群。Docker Swarm允许使用Docker CLI运行swarm命令,因而很容易初始化一组容器,并向组中添加或删除容器。除了Docker Swarm,还有几个其他的容器协调管理器:
如果你对云解决方案感兴趣,可以考虑以下这些:
虽然这些云解决方案都能让你运行容器化应用,每一个都有些细微差别。Google云平台是为Kubernetes定制的,而Azure Container Service可以和Kubernetes, DC/OS, 或Docker的标准Swarm一起工作。 Amazon ECS更像一个服务平台——它自动缩放和管理Docker容器。
使用微服务和容器被视为构建可伸缩,易管理的Web应用的现代方式。如果不容器化你的微服务,会在部署和管理时遇到许多困难。这就是我们为什么使用Docker:避免部署微服务时出现任何问题。添加一个容器协调系统,你就可以无限制地管理你的容器应用。