Spring Boot 脚手架的开箱即用特性,非常利于产品的快速开发,在微服务项目或单一功能的小程序开发项目中经常被使用。
Docker 是一种虚拟化的容器技术,它能在宿主机上虚拟化一台满足最少功能的虚拟主机,这些主机就是容器,多个容器之间,可以共享文件、网络、cpu、内存等资源,当然也可以相互隔离,比起VMWare等虚拟机,它更轻量化,启动速度快,容器支持量多,运维相对容易,虽然在资源隔离上比VMWare等完全化虚拟机稍弱,但在满足业务需求的基础上,docker容器仍然有巨大的优势,许多一线互联网公司也在生产部署了千台万台的docker 容器。在使用场景上,VMWare虚拟机更擅长彻底隔离运行环境,docker通常用于隔离不同的应用服务,数据库,前端,后端程序等等。具体的区别和联系,参考链接OpenStack、KVM、VMWare和Docker。
cgroup是Linux中一个限制、隔离进程组资源(内存、cpu、IO、网络等)的机制,docker是这个机制的一种实现,可以通过参数显式设定资源使用限制及占比(参考Docker 容器使用 cgroups 限制资源使用 )。得益于docker灵活管理资源的特性,在微服务、集群部署、云计算等场景来说无疑会带来很多可能性,架构师需要综合考虑业务需求,产品定位、技术架构、项目成本等各种因素然后做出方案取舍。
那如何将Spring Boot 和docker二者结合起来,让spring boot 应用在docker服务上呢?简单上手实践,步骤如下。
使用Linux系统的发行版本centos7(Red Hat Enterprise Linux Life Cycle)来部署docker服务,需要参考官方文档Install Docker Engine on CentOS,现摘取简要步骤如下:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce docker-ce-cli containerd.io
https://hub-mirror.c.163.com
https://mirror.baidubce.com
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://zindyan5.mirror.aliyuncs.com"]
}
EOF
vi /usr/lib/systemd/system/docker.service
ExecStart 增加如下信息
-H tcp://0.0.0.0:2375
最终效果:ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock
– 开机自动启动
systemctl enable docker
– 重启、重载
systemctl daemon-reload
systemctl restart docker
– 卸载
yum remove docker-ce
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
springboot 作为spring脚手架,利用Ioc容器技术封装好很多默认配置,让编程人员更加专注于业务开发。这里以一个简单的web项目为例,通过IDEA社区版编辑器来进行项目开发。
当然,docker容器完全可以在无网络化的隔离模式下运行,这里就选择spring boot web应用来实现效果!
开发spring boot应用相对比较简单,需要注意的是如何完成docker镜像制作。这里制作一个简单的springboot镜像,容器化后需要实现web的接口请求与响应,其中,controller接口只有一个:
springboot web应用实现镜像封装,可以使用fabric8 docker-maven-plugin插件来完成,无需手动编写Dockerfile,即可直接对springboot应用进行编译制作。
spring boot应用一般会打包成jar包,运行时需要依赖jdk环境,因此docker镜像需要事先准备openjdk这一base层依赖,例如这里插件配置的就是openjkd:8,fabric8 插件通过dockerHost接口检测docker服务器中有无openjdk,不存在会事先下载好,如果已存在则会跳过并快速构建镜像。
fabric8 的docker-maven-plugin插件配置如下,主要关注docker api接口,镜像信息以及运行指令。
<plugin>
<groupId>io.fabric8groupId>
<artifactId>docker-maven-pluginartifactId>
<version>0.26.0version>
<configuration>
<dockerHost>tcp://192.168.73.128:2375dockerHost>
<images>
<image>
<name>study/springboot-simple-demoname>
<build>
<from>openjdk:8from>
<assembly>
<descriptorRef>artifactdescriptorRef>
assembly>
<ports>
<port>8080port>
ports>
<cmd>java -jar maven/${project.name}-${project.version}.jarcmd>
build>
<run>
<ports>
<port>8080:8080port>
ports>
run>
image>
images>
configuration>
<executions>
<execution>
<id>docker:buildid>
<phase>packagephase>
<goals>
<goal>buildgoal>
goals>
execution>
executions>
plugin>
制作docker镜像,除了需要安装依赖的镜像层,当然也需要添加当前的springboot应用层。这里使用idea 已有的maven工具进行应用打包。
如果事先已安装好openjdk镜像层,idea的maven构建工具不仅会构建应用包,也会构建docker镜像,
否则maven工具只会打包springboot应用而不会去构建镜像。
第一次构建时,需要先构建应用包,然后使用docker 插件build即可构建docker 镜像,并在docker服务里看到构建的镜像;如果是已经部署过镜像,依赖的镜像已经安装好,再次制作镜像时可直接通过maven工具build构建。
通过docker image ls (或者docker images) 可查看到刚刚构建的springboot镜像。
通过docker run命令,基于刚刚制作的镜像启动一个容器,然后从浏览器访问宿主机绑定的容器地址信息看看效果,注意启动命令不要忘记配置宿主机和容器端口的端口映射。
通过浏览器的返回结果看,springboot 容器化已经初步完成。
可以把制作好的镜像发布到镜像仓库中,这样利于团队共享和远程管理,这些镜像也可以进行私有化部署,或者部署到其他云厂商提供的仓库,例如道客、阿里云等。这里,我将构建好的镜像推送到阿里云镜像服务器上,方便分享使用,
docker login --username=cut**** registry.cn-shanghai.aliyuncs.com
docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/cutiedocker/springboot-simple-demo:[镜像版本号]
在阿里云镜像仓库中即可查看到推送的镜像,并可以设置访问权限。
对于高并发的web应用,常常部署为如下架构:终端发送请求,通过lvs设备或keepalive系统把请求转发到Nginx服务器,Nginx服务器再转发请求到web服务器,web服务器通过消息中间件,缓存中间件等,将请求发送到后端持久层数据库或仓库,然后依次或各层直接返回响应。在web服务器这层,单应用(tomcat容器)可能无法承受1000+并发请求,需要部署多台应用的集群来实现负载均衡,如果这些web服务器通过docker来进行统一部署和管理,利用一键部署工具,能够减轻运维成本,有利于敏捷开发。