分割我们的业务功能为可重用的服务是个非常有效的方式。
基于REST的服务。
随着容器的出现,我们可以将代码运行在一个完全隔离的容器中。
集装箱化是不是新的虚拟化?
不完全是,它们有共同之处,集装箱和虚拟机都是隔离环境,都是通过控制流程来管理。
两者主要的不同在于每个虚拟机,是一个完整的组件堆栈在运行,从操作系统到应用程序服务,
虚拟硬件模拟包括网络组件,CPUs和内存。
对于集装箱来说,它们操作更像是一个完全隔离的沙箱,只有最小的操作系统内核。
底层的系统资源是共享的。
集装箱最大的优点在于更小的代价的方式运行同样的硬件,比虚拟机更多容器。
这里有一些关键的限制,其中最大的限制在于集装箱只能运行在基于Linux的操作系统上。
隔离的核心源自Linux专有的技术。
我们可以使用Java开发语言,Spring框架来开发REST-service controllers,business services, data repositories.
同样可以用Scala语言,Akka/Play等框架做同样的事。
创建一个完整的解决方案,使用一些列微服务,每个微服务都有自己的容器,自己的持久层,它们都运行在自己的集装箱里,
整个系统的微服务构建成集装箱集群。
One logical business object->One microservice->One git repository folder->One Mongo collection
一个business object可能由多个Objects构成,我们可以将子Object分化到子组件中。
使用Docker可以分为三个阶段:容器创建,容器发布,容器部署
容器创建阶段主要是对配置文件Dockerfile的配置,获取已有的容器镜像,在其基础上应用变化和配置。
安装系统包,拷贝文件,暴露网络端口等。
容器网络:
当我们开启一个容器时,它有自己的私有网络,要跟外部网络交流,容器运行的主机网络端口可以指向单个容器实例的端口。
具体容器的端口则是由Dockerfile指定。
DOCKER_HOST=tcp://192.168.99.100:2376
DOCKER_MACHINE_NAME=default
DOCKER_TLS_VERIFY=1
DOCKER_CERT_PATH=/Users/[username]/.docker/machine/machines/default
常用的Docker命令
docker ps
列出所有正在运行的容器,显示的信息包括ID,名字,基础镜像名,端口
docker build
定义一个容器,它处理Dockerfile并创建一个新的容器定义,我们用来定义自己的微服务容器
docker pull[image name]
从远程库中获取一个容器镜像并存储到本地
docker run
基于本地或者远程容器定义来启动一个容器
docker push
发布一个创建好的容器定义到仓库,通常为DockerHub
容器特定命令
docker stats [container name/ID] [container name/ID]
显示当前载入的每个容器
docker logs [-f] [container name/ID]
显示从容器中最新输出 -f 是跟随输出
docker inspect [container name/ID]
以JSON格式展示左右配置信息
docker port [container name/ID]
显示从容器主机到容器的端口
docker exec [-i] [-t] [container name/ID]
在目标容器上执行一条命令
-i 指定运行交互模式,-t 是pseudo-tty 该命令通常用于获取一个容器shell
docker exec -it [container name/ID] sh
运行mongo
docker run -P -d --name mongodb mongo
-P 告诉Docker显示任何容器声明的端口
-d 运行容器作为后台看护程序
-name mongodb 为容器实例设置名字
最后的mongo 指定使用哪个镜像
docker exec -it mongodb sh
# mongo
MongoDB shell version: 3.0.6
connecting to: test
Server has startup warnings:
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten]
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'.
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten]
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten] ** We suggest setting it to 'never'
2015-09-02T00:57:30.761+0000 I CONTROL [initandlisten]
> use microserviceblog
switched to db microserviceblog
> db.createCollection('testCollection')
{ "ok" : 1 }
运行 docker ps
查看为Mongo Server分配的临时端口
CONTAINER ID IMAGE PORTS NAMES
87192b65de95 mongo 0.0.0.0:32777->27017/tcp mongodb
我们可以看到 主机的32777端口被指定给容器端口27017
因为我们是在vm上运行的主机,所以我们需要回到我们的环境变量里
$ echo $DOCKER_HOST
tcp://192.168.99.100:2376
此时我们就能够通过访问192.168.99.100:32777 来访问我们的Mongo 容器的27017 端口了。
创建一个Spring boot项目
定义 build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.2.0.RELEASE'
}
}
apply plugin: 'spring-boot'
repositories { jcenter()
}
dependencies {
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-web"
}
定义一个员工业务对象
连通持久层
暴露web服务
定义一个Docker容器来运行我们的微服务,包括链上Mongo容器
在DockerMachine上运行容器。
编译jar包:
gradle build
$java -Dspring.data.mongodb.uri=mongodb://192.168.99.100:32777/micros -jar build/libs/Employee.jar
我们定义自己的容器来运行Employee微服务。
首先定义一个Dockerfile:
FROM java:8
VOLUME /tmp
ADD build/libs/Employee.jar app.jar
EXPOSE 8080
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Dspring.data.mongodb.uri=mongodb://mongodb/micros", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
我们开始于一个标准镜像,包含了Java8安装
然后定义一个名为/tmp 的卷
然后从本地文件系统添加一个文件,名为app.jar
指定我们想在容器上使用8080端口
运行命令来 “touch”文件,确保app.jar上的文件修改日期
ENTRYPOINT命令指定为 运行 start 命令
然后我们创建容器镜像
docker build -t microservicedemo/employee
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
microservicedemo/employee latest 364ffd8162b9 15 minutes ago 846.6 MB
下面的问题是,我们的服务容器如何和mongo容器对话呢?
这就需要容器链接,当我们运行一个容器时,我们可以传递一个可选参数-link, 指定新容器需要交互的运行容器的名字
docker run -P -d --name employee --link mongodb microservicedemo/employee
docker exec employee bash -c 'env |grep MONGODB'