目的
通过当前文档的内容,可以将springboot类的微服务项目基于Docker自动构建出成品,可以省去了大量的项目部署时间以及项目依赖环境的部署时间。
阅读本章内容,请确保你已掌握Docker到基本使用,如未满足该要求,请到Docker操作指南中进行学习。
处理流程
- 提交项目业务代码和构建代码到SVN
- Jenkins 构建任务
- 部署包上传FTP
- 测试人员从FTP下载部署包,使用脚本一键安装部署包,开始测试
整体流程如图所示:
下面就围绕上面到处理流程进行微服务项目在Docker环境下到构建及部署教程。
微服务项目
下图是整个项目到结构图:
业务代码及配置说明
业务代码正常修改,正常提交到SVN
在src/main/resources下到application.yml文件中,有如下代码:
db:
server: 192.168.7.200
port: 3306
user: root
pwd: Admin@123
redis:
host: 127.0.0.1
pwd: Admin@123
spring:
profiles: dev
redis:
host: ${db.redis.host}
password: ${db.redis.pwd}
datasource:
url: jdbc:mysql://${db.server}:${db.port}/ms-user?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
driver-class-name: com.mysql.jdbc.Driver
username: ${db.user}
password: ${db.pwd}
其中,关于db部分的,是我自定义的,用于在单个docker容器启动的时候,可以动态的设置其对应的参数值,其实这个参数值,可以使用原生的配置项,只不过我感觉原生的太长了,不利于敲写docker的启动命令,比如,设置数据库的连接地址,如果使用原生的配置项,则需要以下形式:
docker run image-app --spring.datasource.url=jdbc:mysql://x.x.x.x:port/ms-user?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
这样的编写,是很不优雅的,所以,我设置了一个简短的参数用来映射到已经固定到其他参数项中。
例如,设置连接数据库的地址,可以在启动的时候,指定为 --DB_SERVER=x.x.x.x。
部署代码配置说明
在项目目录中的Docker目录中,存在mysql,redis的项目环境依赖的部署配置,如图所示:
项目依赖环境:mysql镜像配置
mysql的基础镜像已经在192.168.7.68上构建完成,且镜像中已经包含了很多配置项,可以直接拿过来使用,而不用再次的去继承mysql官方镜像并且定制各项配置。
项目依赖的mysql镜像中,包含了一个初始化的sql脚本,通过继承基础mysql镜像,生成一个新的带当前项目数据库的镜像。
镜像配置
具体的镜像构建,请参照以下代码或在项目中查看:
#继承mysql的基础镜像
FROM 192.168.7.68:5000/sbr/mysql:1.0.0
#指定维护人
MAINTAINER 圣博润研发中心
#将容器启动后,执行的脚本拷贝到容器内的/docker-entrypoint-initdb.d下,该目录会自动执行sql脚本
COPY ms-user.sql /docker-entrypoint-initdb.d
RUN chmod 775 /docker-entrypoint-initdb.d/ms-user.sql
#声明容器暴漏的端口,只是声明,没有其他作用
EXPOSE 3306
该构建文件中,需要注意以下情况:
- 在将数据库脚本复制到镜像中后,需要为该脚本设置权限,否则,在启动容器的时,会导致mysql的容器启动失败,原因是(ms-user.sql)脚本没有执行权限。
初始化脚本内容需要注意:在mysql官方镜像中提供了容器启动时自动执行/docker-entrypoint-initdb.d文件夹下的脚本的功能(包括shell脚本和sql脚本) docker-entrypoint.sh中的代码如下:
for f in /docker-entrypoint-initdb.d/*; do
case "$f" in
*.sh) echo "$0: running $f"; . "$f" ;;
*.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
*) echo "$0: ignoring $f" ;;
esac
echo
done
就是说只要把你自己的初始化脚本放到/docker-entrypoint-initdb.d/文件夹下,mysql就会读取其中的文件并执行,但是,执行顺序,我们是无法控制的,所以,请尽量将初始化脚本内容写到一个文件中。
项目依赖环境:redis镜像配置
项目同样也依赖redis服务,所以,也需要创建一个redis的镜像。
镜像配置
具体的镜像构建,请参照以下代码或在项目中查看:
#继承redis基础镜像,用来添加属于项目的一些配置
FROM 192.168.7.68:5000/sbr/redis:1.0.0
#编写人/维护人
MAINTAINER 圣博润研发中心
#声明容器暴漏的端口
EXPOSE 6379
该镜像,在目前来看,并没有什么需要注意的地方。
项目镜像配置
将项目的jar包打进基于jre的镜像中,可以生成我们的项目镜像。
镜像配置
具体的镜像构建,请参照以下代码或在项目中查看:
#继承jre8的基础镜像
FROM 192.168.7.68:5000/sbr/jre8:1.0.0
#编写人/维护人
MAINTAINER 圣博润研发中心
#将jar包复制到容器根目录
COPY ms-auth-2.1.2051-SNAPSHOT.jar /ms-auth-2.1.2051-SNAPSHOT.jar
#声明端口
EXPOSE 9003
#容器启动后,执行的命令
ENTRYPOINT ["java", "-jar", "/ms-auth-2.1.2051-SNAPSHOT.jar"]
至此,我们的微服务项目的所有镜像已经制作完毕,后续需要在jenkins中稍加配置处理,就可以生成我们想要的镜像。
compose一键构建
在Docker操作指南中,我们知道,使用compose可以仅仅通过一个命令来根据配置文件构建多个镜像及容器。
镜像构建(build-compose.yml) 配置
使用如下配置文件:
#使用的compose版本
version: '3'
#compose关键字,定义services
services:
#service的名称 sbr_redis
sbr_redis:
#service中容器的名称
container_name: sbr_redis
#使用当前目录下的redis目录下的Dockerfile来创建镜像
build: ./redis
#当前服务向外暴漏的端口
ports:
- "6379:6379"
#service的名称 sbr_mysql
sbr_mysql:
#service中容器的名称
container_name: sbr_mysql
#使用当前目录下的mysql目录下的Dockerfile来创建镜像
build: ./mysql
#当前服务向外暴漏的端口
ports:
- "3306:3306"
#service的名称 sbr_user_auth
sbr_user_auth:
#service中容器的名称
container_name: sbr_app
#使用当前目录下的app目录下的Dockerfile来创建镜像
build: ./app
#当前服务向外暴漏的端口
ports:
- "9003:9003"
通过
docker-compose build
来进行上述mysql、redis、微服务项目镜像的的构建和容器的启动。我们同样可以将这段构建指令配置到jenkins中去。
部署配置
在项目源码目录中,我们发现,还有两个文件没有介绍其内容:
现在,我们来看以下这两个文件是干什么到。
deploy-compose.yml配置
我们已经知道,通过compose可以一键启动docker到多个容器,我们这里就采用来这种方式,而在上一节中,也有一个build-compose.yml到配置文件,那个文件中,其实配置的是,在jenkins构建服务器中到构建镜像到配置。而在测试端也需要提供一个一键启动到compose文件。所以这个deploy-compose.yml文件就是干这个用但。通过jenkins构建后,我们已经明确的知道了我们的镜像名称,所以,可以通过以下配置来一键启动容器,启动的容器都是受compose管理,而不用我们人工去run/create等操作:
#使用的compose版本
version: '3'
#compose关键字,定义services
services:
#service的名称 sbr_redis
sbr_redis:
#service中容器的名称
container_name: sbr_redis
#使用当前目录下的redis目录下的Dockerfile来创建镜像
image: docker_sbr_redis
#当前服务向外暴漏的端口
ports:
- "6379:6379"
#service的名称 sbr_mysql
sbr_mysql:
#service中容器的名称
container_name: sbr_mysql
#使用当前目录下的mysql目录下的Dockerfile来创建镜像
image: docker_sbr_mysql
#当前服务向外暴漏的端口
ports:
- "3306:3306"
#service的名称 sbr_user_auth
sbr_user_auth:
#service中容器的名称
container_name: sbr_app
#使用当前目录下的app目录下的Dockerfile来创建镜像
image: docker_sbr_user_auth
#当前服务向外暴漏的端口
ports:
- "9003:9003"
#当前容器使用的环境变量
environment:
- DB_SERVER=sbr_mysql
- DB_REDIS_HOST=sbr_redis
#当前服务依赖depends_on配置的服务,docker compose会优先启动依赖的服务
depends_on:
- sbr_mysql
- sbr_redis
具体说明已经在配置文件中以注解的方式说明来出来。
部署脚本
我们没有必要提供compose相关的配置文件给测试人员,除非对方坚决的要这个文件,以达到他们自己控制容器操作的目的。
那么,我们可以提供一个更加简便的操作方式来启动各个容器,那就是一个shell脚本:
#!/bin/bash
#定义可执行函数的参数数组
parr=(load startup stop rm rma)
#定义检查本机是否安装了docker
checkDocker(){
dockerpath=$(which docker)
if [ ! -n "#dockerpath" ]; then
echo "未检测到Docker..."
exit 1
fi
}
#载入tar包中的镜像
load(){
checkDocker
#导入docker镜像:mysql
echo "开始导入mysql镜像...."
docker load < sbr_mysql.tar
#导入docker镜像:redis
echo "开始导入redis镜像...."
docker load < sbr_redis.tar
#导入docker镜像:user_auth
echo "开始导入微服务应用镜像...."
docker load < user_auth.tar
}
#开始执行docker容器的启动
startup(){
checkDocker
echo "准备启动容器...."
docker-compose -f deploy-compose.yml up
}
#停止容器
stop(){
checkDocker
echo "准备停止容器...."
docker-compose -f deploy-compose.yml stop
}
#删除容器
rm(){
checkDocker
stop
echo "准备删除容器...."
docker-compose -f deploy-compose.yml rm
}
#删除容器以及镜像
rma(){
checkDocker
rm
echo "准备删除镜像...."
docker_sbr_user_auth_image=$(docker image ls | grep docker_sbr_user_auth)
if [ -n "#docker_sbr_user_auth_image" ]; then
docker rmi docker_sbr_user_auth:latest
fi
docker_sbr_redis_image=$(docker image ls | grep docker_sbr_redis)
if [ -n "#docker_sbr_redis_image" ]; then
docker rmi docker_sbr_redis:latest
fi
docker_sbr_mysql_image=$(docker image ls | grep docker_sbr_mysql)
if [ -n "#docker_sbr_mysql_image" ]; then
docker rmi docker_sbr_mysql:latest
fi
}
if [ ! -n "$1" ] ;then
load
startup
else
if [[ "${parr[@]/$1/}" != "${parr[@]}" ]]; then
$1
else
echo $1":参数不能执行,请输入正确参数!"
exit
fi
fi
通过这个脚本,测试人员可以执行以下命令来简单的进行容器管理:
- load:载入/导入所有镜像,如 ./deploy load
- startup:启动容器,如 ./deploy startup
- stop:停止容器,如 ./deploy stop
- rm:删除容器,如 ./deploy rm
- rma:删除镜像及容器,如 ./deploy rma
README文件介绍
该文件是交给测试人员进行查看到,有以下几点内容:
- 部署脚本如何使用
- 项目升级说明
- 其他备注信息
Jenkins构建
jenkins构建系统:http://192.168.7.26/jenkins/
jenkins的界面如图所示:
我们的构建任务在88.技术中,点击去后,如下图所示:
构建配置
SVN配置
svn配置信息如下图所示:
- Repository URL:填写项目svn地址
- Credentials:SVN账户信息
- Local module directory:将SVN项目down到什么位置,如果是一个点(.),则表示将项目中到内容down到88.技术/微服务2.0目录下,如果什么也没有,则会在微服务2.0目录下创建一个项目名称到目录,然后再将项目内容down到该目录下
构建配置
这一个配置是整个自动化构建的核心
-
maven配置:
shell 操作代码
#先查找jenkins服务器中是否已经构建了微服务项目镜像
#如果已经构建,则删除
docker_sbr_user_auth_image=$(docker image ls | grep docker_sbr_user_auth)
if [ -n "#docker_sbr_user_auth_image" ]; then
docker rmi docker_sbr_user_auth:latest
fi
#先查找jenkins服务器中是否已经构建了微服务项目依赖的redis镜像
#如果已经构建,则删除
docker_sbr_redis_image=$(docker image ls | grep docker_sbr_redis)
if [ -n "#docker_sbr_redis_image" ]; then
docker rmi docker_sbr_redis:latest
fi
#先查找jenkins服务器中是否已经构建了微服务项目依赖的mysql镜像
#如果已经构建,则删除
docker_sbr_mysql_image=$(docker image ls | grep docker_sbr_mysql)
if [ -n "#docker_sbr_mysql_image" ]; then
docker rmi docker_sbr_mysql:latest
fi
#使用项目中的docker目录下的build-compose.yml文件进行构建镜像
docker-compose -f ./docker/build-compose.yml build
#如果88.技术/微服务2.0目录下不存在deploy目录,则创建deploy目录
#如果存在deploy目录,则删除deploy目录下的所有文件,保留一个干净的deploy目录
if [ ! -d "deploy" ];then
mkdir deploy
else
rm -rf deploy/*
fi
#将项目源码的docker目录下的deploy-compose.yml 复制到deploy目录下
cp docker/deploy-compose.yml deploy/deploy-compose.yml
#将将项目源码的docker目录下的script目录下的deploy.sh复制到deploy目录下
cp docker/script/deploy.sh deploy/deploy.sh
#将部署说明复制到deploy目录
cp docker/README.txt deploy/README.txt
#进入deploy目录,并进行镜像的保存,保存的镜像会存到deploy目录下
cd deploy
docker save -o user_auth.tar docker_sbr_user_auth:latest
docker save -o sbr_redis.tar docker_sbr_redis:latest
docker save -o sbr_mysql.tar docker_sbr_mysql:latest
#将导出的镜像打成gz包,并删除源包
tar -zcvf deploy.tar.gz * --remove-files
FTP文件传输配置
此时,jenkins已经在本机构建好了所需的镜像,并且,已经在指定目录将导出的镜像打成了gz包,然后我们将该文件发送到FTP服务器之后,测试人员就可以下载到本机进行测试了。
-
FTP配置
到此,整个jenkins到构建已经完成,我们也可以通过构建控制台来查看实时到构建信息。
部署简要
测试人员操作说明:
到FTP服务器ftp://192.168.7.220中的【测试版本】-【88.技术】-【微服务2.0】中下载最新部署包和部署说明
部署包:deploy.tar.gz 部署说明:README.txt
部署包包含:user_auth.tar(微服务项目镜像),sbr_redis.tar(微服务项目依赖的redis镜像),sbr_mysql.tar(微服务项目依赖的mysql镜像),deploy-compose.yml(测试人员无需关注),deploy.sh(测试人员主要的操作文件)
-
deploy.sh的使用:
- 使用 tar -zxvf deploy.tar.gz来解压部署包
- 脚本一键执行:
- 脚本会检查本机是否安装docker,如果未安装,会给出提示
- 给脚本赋予可执行权限: chmod 775 deploy.sh
- 脚本参数介绍:
如果只是输入了 ./deploy 而不附带任何参数,该脚本会自动导入镜像并启动容器
load:载入所有镜像,如 ./deploy load
startup:启动容器,如 ./deploy startup
stop:停止容器,如 ./deploy stop
rm:删除容器,如 ./deploy rm
rma:删除镜像及容器,如 ./deploy rma
至此,微服务项目在jenkins中基于Docker的构建的内容已经完毕,若有不足之处,请予以支持与补充。谢谢。