使用Docker的多层体系结构教程

背景

尽管目前有很多非常好的Docker教程,但我发现许多教程要么在提供的场景中过于简单,要么在某些情况下太过复杂了。 因此,我决定编写自己的教程,描述使用Docker配置的多层架构。

先决条件

本教程假定您已成功安装Git和Docker。 我在Mac上运行Boot2Docker,这使Docker几乎可以像本地安装在Mac上一样运行(在PC上,Boot2Docker并不那么简单)。 我假设对Docker有一定的基本了解(很好的信息来源是https://docs.docker.com/articles/basics/ )。

情境

我为本教程开发的场景如下所示:

dd

如您所见,它涉及多个层次:

MongoDB :这是我们的持久层,其中将填充一些代表客户的演示数据。

API服务器 :此层代表Restful API服务。 它公开了打包为JSON的mongo数据(就本教程而言,它实际上并未使用通常会出现的任何业务逻辑)。 该层是使用Spring Web Services和Spring Data用Java开发的。

WebClient :这是一个非常简单的层,演示了用Google的Polymer UI框架编写的Web应用程序。 所有业务逻辑都驻留在Javascript中,然后使用CORS隧道从服务层访问API数据。

我不会在每个层的实现上花费很多时间,因为它与本Docker教程的目的并不相关。 我将简要介绍一些代码逻辑,只是为了设置上下文。 让我们开始看看持久层是如何配置的。

MongoDB配置

注意:该层的项目代码位于: https : //github.com/dajevu/docker-mongo

Dockerhub包含mongo的正式映像,我们将以此为起点( https://registry.hub.docker.com/u/dockerfile/mongodb/ )。 万一我们需要基于该映像中安装的内容,我决定通过简单地复制其Dockerfile(映像可以是二进制文件,也可以通过文本Dockerfile声明性地)来克隆映像。 这是Dockerfile:

img1

第5行标识用于mongo安装的基本映像-这是官方的dockerfile / ubuntu映像。 由于未指定任何版本,因此我们正在获取最新版本。

注意 :Dockerfiles中的注释以#开头。

第8行开始安装mongo数据库以及一些其他工具,例如s curl,git等。Ubuntu的apt-get是Ubuntu的标准软件包管理工具。

第16和18行为mongo数据库文件所在的位置设置了一些挂载点(以及git挂载点,以备日后使用)。 在第21行,我们将工作目录设置为该数据安装点的位置(从第16行开始)。

最后,我们确定Mongo需要暴露的一些端口(第27和28行)。

假设您已从我的git存储库( https://github.com/dajevu/docker-mongo )中获取了代码,则可以通过运行脚本runDockerMongo.sh来启动启动此Docker映像(在Windows Boot2Docker中,您需要在运行Docker的VM容器中获取代码)。 该脚本仅包含以下内容:

docker run -t -d -p 27017:27017 --name mongodb jeffdavisco/mongodb mongod --rest --httpinterface --smallfiles

运行时,它将使用目录中存在的Dockerfile启动容器。 您可以使用docker ps命令确认它正在运行:

img2

从上面可以看到,在这种情况下,它使用4fb383781949容器ID启动了Mongo。 有了容器ID后,您可以使用以下方法查看容器的服务器日志:

docker logs --tail="all" 4fb383781949 #container Id

如果您看不到docker ps的任何结果,则意味着该容器已启动但随后立即退出。 尝试发出命令docker ps -a-这将确定失败服务的容器ID,然后您可以使用docker logs来确定出了什么问题。 您需要先删除该容器,然后再使用docker rm启动新容器。

Mongo容器运行后,我们现在可以用一些演示数据填充它,这些数据将用于API服务层。 项目文件中存在一个名为northwind-mongo-master目录,该目录包含一个名为mongo-import-remote.sh的脚本。 让我们看一下该文件的内容:

img3

该脚本仅运行目录中存在的每个.csv文件,并使用mongoimport实用程序加载集合。 但是,有一点皱纹。 由于mongoimport正在连接到远程mongo数据库,因此需要远程主机的IP地址,并且此远程主机是刚启动的mongo容器。 如何确定要使用的IP地址? 如果您使用的是Boot2Docker,则只需运行boot2docker ip这将为您提供所使用的Docker主机的IP地址。 如果直接在运行Docker的主机中运行,则可以通过localhost作为您的IP地址进行连接(因为该端口在启动容器时公开给Docker主机)。

为了加载测试数据,请更新该脚本,使其具有适合您的环境的IP地址。 然后,您可以运行脚本( mongo-import-remote.sh ),它将使用示例数据填充mongo数据库。 如果您使用的是MongoHub,则可以连接到远程mongo主机,并查看以下可用集合:

img4

幸运的是,我们不必在剩余的容器上经历这些障碍。

API服务层配置

API服务是一个非常简单的基于Restful的Web服务,它仅以JSON格式公开了一些mongo数据(当然,您可以通过其Restful API直接访问mongo,但是在大多数实际情况下,您永远不会公开曝光)。 用Java Spring编写的Web应用程序使用Spring数据库来访问远程mongo数据库。

该层的项目文件位于: https : //github.com/dajevu/docker-maven-tomcat 。 尽管我不会介绍所有Spring配置/设置(毕竟,这不是Spring演示),但让我们简要地看一下将具有公开Web服务的主要服务类:

img5

使用Spring Web服务的Spring注释,我们在第5行中对该控制器进行注释,以便Spring可以使用基本URL /customer公开后续服务。 然后,我们定义一种方法,该方法用于公开Mongo集合中的所有客户数据。 CustomerDAO类包含与Mongo接口的逻辑。

让我们看一下用于运行此Web服务的Dockerfile(使用Jetty作为Web服务器):

img6

如您所见,在第2行中,我们将API服务的基本映像标识为Java 7映像。 与mongo Dockerfile相似,我们在第8-15行中要做的下一步是安装各种必需的依赖项,例如git,maven和mongo客户端。

然后,与mongo Dockerfile不同,我们使用git来安装Java Web应用程序。 这是在第21至26行中完成的。我们为源文件创建一个位置,然后使用git clone安装它们。 最后,在第28行,我们的shell脚本名为run.sh 让我们看一下脚本内容:

#!/bin/bash
echo `env`
mvn jetty:run

如您所见,这非常少。 我们首先从此容器中回显环境变量,以便出于故障诊断目的,在检查docker日志时可以看到它们。 然后,我们只需使用mvn jetty:run启动Web应用程序。 由于已经通过git clone下载了应用程序的源代码,因此maven将自动编译webapp,然后启动jetty Web服务器。

现在,您可能想知道,Web服务如何知道如何连接到Mongo数据库? 当我们将Mongo数据库端口公开给docker主机时,如何在Java应用程序中定义连接,以便它指向正确的位置。 这是通过使用在两个容器之间指定依赖项/链接时自动创建的环境变量来完成的。 为了了解它是如何实现的,让我们看一下用于启动容器的启动脚本runDockerMaven.sh

docker run -d --name tomcat-maven -p 8080:8080 
\ —link mongodb:mongodb jeffdavisco/tomcat-maven:latest 
\ /local/git/docker-maven-tomcat/run.sh

如您所见, -link选项用于通知docker该容器与另一个容器(在本例中为Mongo实例)具有依赖性。 如果存在,-link选项将创建一组环境变量,这些变量在启动容器时填充。 让我们使用docker logs命令检查这些环境变量的外观(记住,在启动此容器之前,必须先运行mongo容器):

MONGODB_PORT_28017_TCP_PROTO=tcp 
HOSTNAME=f81d981f5e9e 
MONGODB_NAME=/tomcat-maven/mongodb 
MONGODB_PORT_27017_TCP=tcp://172.17.0.2:27017 
MONGODB_PORT_28017_TCP_PORT=28017 
MONGODB_PORT=tcp://172.17.0.2:27017 
MONGODB_PORT_27017_TCP_PORT=27017 
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 
PWD=/local/git/docker-maven-tomcat 
MONGODB_PORT_27017_TCP_PROTO=tcp 
JAVA_HOME=/usr/lib/jvm/java-7-oracle MONGODB_PORT_28017_TCP_ADDR=172.17.0.2 MONGODB_PORT_28017_TCP=tcp://172.17.0.2:28017 
MONGODB_PORT_27017_TCP_ADDR=172.17.0.2

MONGODB开头的环境变量表示通过链接创建的环境变量。 如何知道以MONGODB为前缀? 这是因为,当我们启动mongo容器时,我们指定了可选的—name参数,该参数为该容器提供了名称别名。

现在,如何将其整合到API服务中? 在定义用于访问mongo的Spring Data属性时,我们指定使用环境变量来标识主机。 这是在spring-data.xml文件中完成的(位于项目代码中的src / main / resources下)。

threads-allowed-to-block-for-connection-multiplier="4"
                   connect-timeout="1000"
                   max-wait-time="1500"
                   auto-connect-retry="true"
                   socket-keep-alive="true"
                   socket-timeout="1500"
                   slave-ok="true"
                   write-number="1"
                   write-timeout="0"
                   write-fsync="true" />

因此,当我们启动容器时,所需runDockerMaven.sh就是使用runDockerMaven.sh启动它。 通过使用以下方法通过浏览器访问服务来确认该服务正在运行:

在您的环境中,如果使用的是Boot2Docker,请运行boot2docker ip来标识公开服务的IP地址。 如果直接在Docker主机上运行,​​则应该能够指定localhost。 这应该带回一些JSON客户数据,例如:

img8

现在,让我们看一下最后一个容器,该容器用于通过网页公开数据。

Web应用程序层

Web应用程序层由轻量级Python Web服务器组成,该服务器仅提供静态HTML页面以及相应的Javascript。 该页面使用Google的Polymer UI框架在浏览器中显示客户结果。 为了允许Polymer直接与API服务进行通信,在API服务器上配置了CORS以允许入站请求(我想使Web应用程序层尽可能轻便)。

注意:可以在以下位置找到该层的源代码/项目文件: https//github.com/dajevu/docker-python

这是Javascript中进行远程调用的相关代码:

img9

显然, url属性中存在的VMHOST值不是有效的域名。 相反,当启动Docker容器时,它将用API服务器的实际IP替换该值。 在深入了解这一点之前,让我们首先检查用于Python服务器的Dockerfile:

img10

这个Dockerfile与我们一直在使用的其他文件非常相似。 像mongo容器一样,该容器基于ubuntu官方图片。 然后,在第11-14行中指定已加载Python和相关库。 在23-24行中,我们为git源代码准备了一个目录。 接下来,我们在第27行使用git clone提取代码,然后将工作目录设置到该位置(第28行)。 (实际上,第31行的CMD命令被忽略了,因为我们在启动脚本中指定了要运行的命令(即,它覆盖了Dockerfile中的命令)。

让我们看一下现在用于启动容器的启动脚本:

docker run -d -e VMHOST=192.168.59.103 --name python -p 8000:8000 \ 
--link tomcat-maven:tomcat jeffdavisco/polymer-python:latest \
/local/git/docker-python/run.sh

上面需要注意的几件事。 注意如何使用环境标志-e VMHOST=192.168.59.103传递Boot2Docker实例的IP地址。 与配置API服务层时需要执行的操作类似,您将必须针对您的环境进行修改(如果使用Boot2Docker,请运行boot2docker ip以找到您的boot2docker ip主机的IP地址,或者如果在Linux上本地运行,则可以使用本地主机)。 注意,我们正在做的另一件事是暴露端口8000,这是我们的Python Web服务器将在其下运行的位置。 最后,我们指示Docker容器运行run.sh shell脚本。 接下来我们来看。

run.sh脚本包含以下内容:

#!/bin/bash

# replace placeholder with actual docker host
sed -i "s/VMHOST/$VMHOST/g" post-service/post-service.html

python -m SimpleHTTPServer 8000

sed命令用于使用启动时传递给$VMHOST容器的环境变量( $VMHOST )替换该VMHOST占位符令牌。 html文件更新后,我们将使用命令python -m SimpleHTTPServer 8000启动python服务器。 运行启动脚本后,如果一切顺利,则应该能够在浏览器中访问: http://:8000 (其中dockeriphost等于您的boot2docker ip地址,如果在Linux上则为本地docker主机)。 您应该看到类似以下内容:

img11

您现在已经完成了本教程! 您有一个运行mongo的docker容器; 另一个正在运行API服务; 以及最后运行的简单Web服务。 我希望您喜欢本教程,并希望对其有一个后续介绍,以简短地描述如何使用fig可以更轻松地管理这些容器(在http://www.fig.sh/上了解更多信息 )。

翻译自: https://www.javacodegeeks.com/2015/02/multi-tier-architecture-tutorial-using-docker.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值