微服务项目在jenkins中基于Docker的构建

目的

       通过当前文档的内容,可以将springboot类的微服务项目基于Docker自动构建出成品,可以省去了大量的项目部署时间以及项目依赖环境的部署时间。
       阅读本章内容,请确保你已掌握Docker到基本使用,如未满足该要求,请到Docker操作指南中进行学习。

处理流程

  • 提交项目业务代码和构建代码到SVN
  • Jenkins 构建任务
  • 部署包上传FTP
  • 测试人员从FTP下载部署包,使用脚本一键安装部署包,开始测试

整体流程如图所示:


process.png

下面就围绕上面到处理流程进行微服务项目在Docker环境下到构建及部署教程。

微服务项目

下图是整个项目到结构图:


project.jpg

业务代码及配置说明

       业务代码正常修改,正常提交到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的项目环境依赖的部署配置,如图所示:


dockerFolder.png

项目依赖环境: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.png

现在,我们来看以下这两个文件是干什么到。

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的界面如图所示:

jenkins_main.png

我们的构建任务在88.技术中,点击去后,如下图所示:
kenkins_list.png

构建配置

SVN配置

svn配置信息如下图所示:

  • Repository URL:填写项目svn地址
  • Credentials:SVN账户信息
  • Local module directory:将SVN项目down到什么位置,如果是一个点(.),则表示将项目中到内容down到88.技术/微服务2.0目录下,如果什么也没有,则会在微服务2.0目录下创建一个项目名称到目录,然后再将项目内容down到该目录下
jenkins_svn.png

构建配置

这一个配置是整个自动化构建的核心

  • maven配置:


    jenkins_maven.jpg
  • 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.png

到此,整个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的使用:

    1. 使用 tar -zxvf deploy.tar.gz来解压部署包
    2. 脚本一键执行:
      • 脚本会检查本机是否安装docker,如果未安装,会给出提示
      • 给脚本赋予可执行权限: chmod 775 deploy.sh
      • 脚本参数介绍:
        如果只是输入了 ./deploy 而不附带任何参数,该脚本会自动导入镜像并启动容器
        load:载入所有镜像,如 ./deploy load
        startup:启动容器,如 ./deploy startup
        stop:停止容器,如 ./deploy stop
        rm:删除容器,如 ./deploy rm
        rma:删除镜像及容器,如 ./deploy rma

至此,微服务项目在jenkins中基于Docker的构建的内容已经完毕,若有不足之处,请予以支持与补充。谢谢。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352

推荐阅读更多精彩内容