使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架

简介: 本文讲的是使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架,【编者的话】Consul是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用Go语言开发,基于 Mozilla Public License 2.0 的协议开源。
本文讲的是使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架 【编者的话】Consul是一个支持多数据中心分布式高可用的服务发现和配置共享的服务软件,由 HashiCorp 公司用Go语言开发,基于 Mozilla Public License 2.0 的协议开源。本文介绍了如何使用Consul将多个Docker容器组合起来,以提供一个高可扩展的Web服务。
docker_whale.png_1411805342_.jpg_1421807584_.jpg

当你开始将容器拼装起来构建你的系统的时候,你会发现Docker非常有趣。最近,我在玩 Consul ,并尝试用它来构建一个高可扩展的Web应用框架。Consul是 HashiCorp Vagrant 的创建者)开发的一个 服务发现与配置 项目。

我之前尝试借助SRV的记录使用Consul来创建一个可扩展的框架(详情请见: here ),但我发现这种方式有点复杂。而我追求简单,所以我又发现了 Consul Template ,当添加或者移除服务时,Consul Template可以通过连接Consul更新配置并重启应用。

在这篇文章中,我将会讲述如何使用Docker将Consul、Consul Template、Registrator和Nginx组装成一个值得信任且可扩展的框架——DR CoN。一旦组装完成,DR CoN就可以让你在这个框架中添加和移除服务,关键是你不需要重写任何配置,也不需要重启任何服务,一切都能正常运行!

Docker

Docker在LXC的基础上(Linux Containers)上包装了一些API,所以它只能运行在Linux上(注[1])。由于我使用的是OS X操作系统(读者中可能大部分人都是),为此我写了 “ 通过Boot2Docker在OSX上运行Docker ”这篇文章,以下是简要介绍:
brew install boot2docker
boot2docker init  
boot2docker up

执行之后,将在Ubuntu上启一个虚拟机来运行Docker daemon。为了连上daemon,执行以下命令:
export DOCKER_IP=`boot2docker ip`  
export DOCKER_HOST=`boot2docker socket`

你可以通过执行下述命令来验证Docker是否成功安装:
docker ps

通过Docker构建一个简单的Web服务

我们需要一个服务来测试Dr Con这个框架。为此,让我们开始构建一个我了解的简单服务(详情请见 此文 )。创建一个 Dockerfile 文件,将以下内容写入其中:
FROM  python:3  
EXPOSE  80  
CMD ["python", "-m", "http.server"]

在Dockerfile文件所在目录下执行以下命令:
docker build -t python/server .

执行后,将创建一个名为  python/server  的镜像,通过执行以下命令运行一个容器:
docker run -it \
-p 8000:80 python/server

我们可以通过 curl 命令调用这个简单服务来测试它是否能够正常运行:
curl $DOCKER_IP:8000

Consul

Consul是一个拥有DNS和HTTP API的服务。它还有很多其它功能,例如服务健康检测、跨主机集群构建和“键-值”对存储库。执行以下命令在Docker container中运行Consul:
docker run -it -h node \
 -p 8500:8500 \
 -p 8600:53/udp \
 progrium/consul \
 -server \
 -bootstrap \
 -advertise $DOCKER_IP \
 -log-level debug

如果你通过浏览器能够访问 $DOCKER_IP:8500 ,你将在控制面板上看到Consul中已经注册的所有服务。

我们能够通过 curl 向Consul的Web API注册一个服务:
curl -XPUT \
$DOCKER_IP:8500/v1/agent/service/register \
-d '{
 "ID": "simple_instance_1",
 "Name":"simple",
 "Port": 8000, 
 "tags": ["tag"]
}'

然后,我们可以通过  dig  命令查询Consul为这个提供的DNS API:
dig @$DOCKER_IP -p 8600 simple.service.consul

执行后,结果如下:
; <<>> DiG 9.8.3-P1 <<>> simple.service.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 39614
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;simple.service.consul.        IN    A

;; ANSWER SECTION:
simple.service.consul.    0    IN    A    192.168.59.103

;; Query time: 1 msec
;; SERVER: 192.168.59.103#53(192.168.59.103)
;; WHEN: Mon Jan 12 15:35:01 2015
;; MSG SIZE  rcvd: 76

等等,这有个问题,服务的端口号在哪?很遗憾,DNS的记录中并没有返回服务的端口号。为了获取端口号,我们必须检查SRV记录:
dig @$DOCKER_IP -p 8600 SRV simple.service.consul

执行后,结果如下:
; <<>> DiG 9.8.3-P1 <<>> SRV simple.service.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3613
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;simple.service.consul.        IN    SRV

;; ANSWER SECTION:
simple.service.consul.    0    IN    SRV    1 1 8000 node.node.dc1.consul.

;; ADDITIONAL SECTION:
node.node.dc1.consul.    0    IN    A    192.168.59.103

;; Query time: 1 msec
;; SERVER: 192.168.59.103#53(192.168.59.103)
;; WHEN: Mon Jan 12 15:36:54 2015
;; MSG SIZE  rcvd: 136

SRV记录很难用,因为很多技术不支持它们。

srv-router 这个容器被Consul和Nginx用来路由访问请求到相应服务(详情请见: here )。但是,下面我们将介绍一种更简单的方式让Nginx路由这些请求到相应服务。

Registrator

在Docker容器启动后,Registrator配置好相应的环境变量并将这个容器注册到Consul上,示例如下:
docker run -it \
-v /var/run/docker.sock:/tmp/docker.sock \
-h $DOCKER_IP progrium/registrator \
consul://$DOCKER_IP:8500

Registrator启动后,我们运行一个服务:
docker run -it \
-e "SERVICE_NAME=simple" \
-p 8000:80 python/server

命令执行后,这个服务被自动添加到Consul,同理,如果我们关闭这个服务,它在Consul上会被自动移除。由于Registrator不需要我们手动将服务注册到Consul,因此它是DR CoN需要组装的第一部分。

Consul Template

Consul Template 的作用是,当它发现Consul上的服务有变化时,它会利用Consul更新文件并执行相应的命令。

比如说,它能够重写 nginx.conf 这个文件,将所有服务的路由信息列入其中,然后重新加载Nginx的配置,使得多个相似服务达到负载均衡,或者给多种服务提供一个单一的终端。

我对这个Docker容器做了如下修改(详情请见这里):
FROM nginx:1.7

#Install Curl
RUN apt-get update -qq && apt-get -y install curl

#Download and Install Consul Template
ENV CT_URL http://bit.ly/15uhv24
RUN curl -L $CT_URL | \
tar -C /usr/local/bin --strip-components 1 -zxf -

#Setup Consul Template Files
RUN mkdir /etc/consul-templates
ENV CT_FILE /etc/consul-templates/nginx.conf

#Setup Nginx File
ENV NX_FILE /etc/nginx/conf.d/app.conf

#Default Variables
ENV CONSUL consul:8500
ENV SERVICE consul-8500

# Command will
# 1. Write Consul Template File
# 2. Start Nginx
# 3. Start Consul Template

CMD echo "upstream app {                 \n\
  least_conn;                            \n\
  {{range service \"$SERVICE\"}}         \n\
  server  {{.Address}}:{{.Port}};        \n\
  {{else}}server 127.0.0.1:65535;{{end}} \n\
}                                        \n\
server {                                 \n\
  listen 80 default_server;              \n\
  location / {                           \n\
    proxy_pass http://app;               \n\
  }                                      \n\
}" > $CT_FILE; \
/usr/sbin/nginx -c /etc/nginx/nginx.conf \
& CONSUL_TEMPLATE_LOG=debug consul-template \
  -consul=$CONSUL \
  -template "$CT_FILE:$NX_FILE:/usr/sbin/nginx -s reload";

下载这个Dockerfile,请点击这里

注意: 上面的 \n\ 表示另起一行,并且为Docker的多行命令去除换行。

这个Docker容器将会运行Consul Template和Nginx,当服务有变化时,它将重写Nginx的 app.conf 文件并且重新加载Nginx。

通过以下命令构建这个容器:
docker build -t drcon .

然后,启动容器:
docker run -it \
-e "CONSUL=$DOCKER_IP:8500" \
-e "SERVICE=simple" \
-p 80:80 drcon

SERVICE  选项用来指定Consul上的服务。因此,上面这个DR CoN 容器将会通过所有命名为  simple  的服务来达到负载均衡。

组装到一起

现在让我们把一切都组装起来。

运行Consul:
docker run -it -h node \
 -p 8500:8500 \
 -p 53:53/udp \
 progrium/consul \
 -server \
 -bootstrap \
 -advertise $DOCKER_IP

运行Registrator:
docker run -it \
-v /var/run/docker.sock:/tmp/docker.sock \
-h $DOCKER_IP progrium/registrator \
consul://$DOCKER_IP:8500

运行DR CoN:
docker run -it \
-e "CONSUL=$DOCKER_IP:8500" \
-e "SERVICE=simple" \
-p 80:80 drcon

执行  curl $DOCKER_IP:80  命令,结果如下:
curl: (52) Empty reply from server

现在开启  simple  的服务:
docker run -it \
-e "SERVICE_NAME=simple" \
-p 8000:80 python/server

执行后,将发生:
  1. Registrator将这个服务注册到Consul;
  2. Consul Template重写nginx.conf,然后重新加载配置。

现在执行 curl $DOCKER_IP:80 将成功路由到这个服务。

如果我们在其他端口上启动另一个simple服务:
docker run -it \
-e "SERVICE_NAME=simple" \
-p 8001:80 python/server

请求将通过这两个simple服务进行负载均衡。

有趣的是,我们可以执行 while true; do curl $DOCKER_IP:80; sleep 1; done 这个脚本,当关闭或者启动simple服务时,脚本仍在快速运行且所有请求都能正常进行。

总结

借助Docker,描述、分布和实现DR CoN这类框架变得更加容易,当然也少不了Consul这么好用的工具。使用Docker更加强大的工具来组装服务是非常有趣和有用的,现在我就能创建一种横向可扩展的框架,并且一切都能正常运行。

注[1]:  Docker在1.2版本之后就默认使用libcontainer,而不是LXC,虽然Docker支持LXC。由于不论libcontainer和LXC都是基于Linux Kernel中的namespace和Cgroup,所以现在只能运行在Linux上。

原文链接:Scalable Architecture DR CoN: Docker, Registrator, Consul, Consul Template and Nginx(翻译: 肖远昊 校对:李颖杰)

===========================

译者介绍

肖远昊,硕士研究生,就读于北京航空航天大学计算机学院ACT实验室,目前从事虚拟化、云计算方向的研究。希望通过DockerOne与大家一起交流和学习Docker。

原文发布时间为:2015-03-26
本文作者:xiaoyh 
本文来自云栖社区合作伙伴DockerOne,了解相关信息可以关注DockerOne。
原文标题:使用Docker、Registrator、Consul、Consul Template和Nginx实现高可扩展的Web框架
目录
相关文章
|
2月前
|
应用服务中间件 网络安全 nginx
手把手教你使用 Docker 部署 Nginx 教程
本文详解Nginx核心功能与Docker部署优势,涵盖镜像拉取、容器化部署(快速、挂载、Compose)、HTTPS配置及常见问题处理,助力高效搭建稳定Web服务。
1147 4
|
5月前
|
关系型数据库 应用服务中间件 nginx
Docker一键安装中间件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)
本系列脚本提供RocketMQ、Nginx、MySQL、MinIO、Jenkins和Redis的Docker一键安装与配置方案,适用于快速部署微服务基础环境。
|
2月前
|
应用服务中间件 Linux nginx
在虚拟机Docker环境下部署Nginx的步骤。
以上就是在Docker环境下部署Nginx的步骤。需要注意,Docker和Nginix都有很多高级用法和细节需要掌握,以上只是一个基础入门级别的教程。如果你想要更深入地学习和使用它们,请参考官方文档或者其他专业书籍。
157 5
|
7月前
|
存储 应用服务中间件 nginx
在使用Nginx之后,如何在web应用中获取用户IP以及相关原理
但总的来说,通过理解网络通信的基础知识,了解http协议以及nginx的工作方式,我们已经能在大多数情况下准确地获取用户的真实IP地址了,在调试问题或者记录日志时会起到很大的帮助。
379 37
|
10月前
|
中间件 关系型数据库 数据库
docker快速部署OS web中间件 数据库 编程应用
通过Docker,可以轻松地部署操作系统、Web中间件、数据库和编程应用。本文详细介绍了使用Docker部署这些组件的基本步骤和命令,展示了如何通过Docker Compose编排多容器应用。希望本文能帮助开发者更高效地使用Docker进行应用部署和管理。
322 19
|
9月前
|
运维 网络安全 文件存储
找不到类似 Docker Desktop 的 Web 管理界面?试试这些开源方案
Docker Desktop 是本地容器化开发的利器,但存在无法通过 Web 远程管理、跨平台体验不一致等问题。为此,推荐几款轻量级、可 Web 化管理的 Docker 工具:Portainer 功能全面,适合企业级运维;CasaOS 集成应用商店和 NAS 功能,适合家庭/个人开发环境;Websoft9 提供预集成环境,新手友好。这些工具能有效提升容器管理效率,满足不同场景需求。
568 3
|
11月前
|
前端开发 应用服务中间件 nginx
docker安装nginx,前端项目运行
通过上述步骤,你可以轻松地在Docker中部署Nginx并运行前端项目。这种方法不仅简化了部署流程,还确保了环境的一致性,提高了开发和运维的效率。确保按步骤操作,并根据项目的具体需求进行相应的配置调整。
989 25
|
开发者 Docker Python
从零开始:使用Docker容器化你的Python Web应用
从零开始:使用Docker容器化你的Python Web应用
518 4
|
应用服务中间件 Linux nginx
Docker镜像-手动制作yum版nginx镜像
这篇文章介绍了如何手动制作一个基于CentOS 7.6的Docker镜像,其中包括下载指定版本的CentOS镜像,创建容器,配置阿里云软件源,安装并配置nginx,自定义nginx日志格式和web页面,最后提交镜像并基于该镜像启动新容器的详细步骤。
400 21
Docker镜像-手动制作yum版nginx镜像
|
机器学习/深度学习 数据采集 Docker
Docker容器化实战:构建并部署一个简单的Web应用
Docker容器化实战:构建并部署一个简单的Web应用