在微服务时代,服务数量及规模越来越大,服务的部署及运维的模式如果仍然采用传统方式就会大大增加运维成本。所以微服务时代的运维方式一定是Devops模式,通过构建自动化运维发布平台来打通产品、开发、测试及运维流程,从而整体上提升研发效能,而这也是目前大部分公司正在做的事情。
随着以Docker为代表的容器化技术的普及,目前Devops实践大多会采用容器(如Docker、K8s)这样的方式来作为微服务应用部署运行的载体,并通过容器的弹性扩展来实现快速扩容和缩容,从而更快地响应业务、更好地利用资源。
目前Devops最流行的部署方案是基于K8s的集群方案,但是它本身也是基于Docker容器技术的,所以在接触K8s技术之前,先通过本文了解下Docker及基于Docker的容器化部署。
Docker是一个开源的应用容器引擎,也是目前最流程的应用部署方式,通过它可以把应用及其依赖打包到一个可移植的镜像中,然后利用Docker提供的部署机制将其发布至任意安装了Docker容器的系统环境中。从使用角度主要需要理解一下几个要点如图所示:
如上图所示,理解Docker的使用方式需要掌握以下几个概念:
为了更进一步加深对上述概念的理解,这里以一个Spring Boot应用为例演示如何通过Docker部署一个Spring Boot服务。这里可以通过IDE创建一个简单的Spring Boot应用并写一个测试接口,如下图所示:
以上为通过IDEA创建的一个最为简单的Spring Boot应用程序,运行后启动服务可以通过端口访问测试接口,接下来使用Docker部署该服务,步骤如下:
创建Dockerfile文件构建Docker镜像
按照前面Docker的介绍,如果要让Spring Boot程序运行在Docker容器上,首先需要构建Docker镜像,而构建的过程则需要通过Dockerfile文件来描述。例如在项目src/main/docker目录创建Dockerfile文件,代码如下:
FROM JAVA:8
VOLUME /tmp
RUN mkdir /App
ADD springboot-1.0-SNAPSHOT.jar /app/springboot.jar
ADD runboot.sh /app/
RUN bash -c 'touch /app/springboot.jar'
WORKDIR /app
RUN chmod a+x runboot.sh
EXPOSE 9090
CMD /app/runboot.sh
上述Dockerfile文件定义了运行的基础信息为JDK1.8、容器运行的目录为/app、并添加了所需的Jar包等信息,最后定义了要执行的命令为“/app/runboot.sh”脚本。runboot.sh脚本代码如下:
sleep 10
java -Djava.security.egd=file:/dev/./urandom -jar /app/springboot.jar
这里打包Spring Boot应用Docker镜像的Dockerfile文件就定义好了,为了能在Maven项目中执行Docker镜像构建命令,还需要在项目pom.xml文件添加Maven Build插件信息,代码如下:
<!--Docker Maven插件依赖-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<imageName>${project.name}:${project.version}</imageName>
<dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
<skipDockerBuild>false</skipDockerBuild>
<resources>
<resource>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
接下来可以通过Maven命令构建Spring Boot应用Docker镜像,命令如下:
mvn clean package docker:build
运行成功可以看到本地Docker仓库中镜像信息,命令如下:
这表示Spring Boot程序的Docker镜像已打好,需要说明的是以上命令运行是需要你的系统已经安装Docker容器运行环境。
创建docker-compose.yml文件
有了Docker镜像,如何将镜像作为容器启动以及该镜像中启动那些服务、它的资源限制及网络使用什么方式,这些都是docker-compose文件定义的,其代码如下:
version: '3.2'
services:
springboot:
image: springboot:1.0-SNAPSHOT
hostname: springboot
environment:
- SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:-debug}
ports:
- "9999:9090"
networks:
- mynet
networks:
mynet:
external: true
在上述docker compose文件中定义了一个springboot服务,然后针对该服务描述了其所使用的Docker镜像、环境变量参数、容器端口映射及网络等信息。需要说明的是services下面还可以定义服务,stack(应用)与service(服务)的关系在docker-compose中是一对多的关系,只是这里暂时没有需要定义其他服务。
启动Docker容器实现应用容器部署
通过上述准备,此时就可以通过docker-compose启动Spring Boot应用的Docker镜像,目录切换到src/main/docker目录,执行如下命令:
$ docker-compose up -d
Creating docker_springboot_1 ... done
此时应用就已经通过Docker容器部署了,可以通过如下命令进行查看:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4117e4a8963e springboot:1.0-SNAPSHOT "/bin/sh -c /app/run…" 5 seconds ago Up 3 seconds 9090/tcp, 0.0.0.0:9999->9999/tcp docker_springboot_1
到这里就大功告成了,访问9999端口就能够访问到Docker容器中的Spring Boot服务了。