Jenkins+Gitlab+Docker实现SpringBoot项目自动化部署

Jenkins+Gitlab+Docker实现SpringBoot项目自动化部署

Scroll Down

1.使用Docker搭建Jenkins

1.1 拉取Jenkins镜像

我们这里选择jenkins/jenkins:lts版本的Jenkins,因为Jenkins:latest版本是官方版本,而且是英文的,下载插件什么的因为墙的各种原因导致无法下载和下载报错.

docker pull jenkins/jenkins:lts

1.2 创建目录

为了方便后期Jenkins中配置文件的修改,同时,防止jenkins中重要文件因为容器损毁或删除导致文件丢失,因此需要将/var/jenkins_home目录对外挂载

mkdir -p /apps/devops/jenkins

对目录开放docker进程操作的完全读写的权限

chmod 777 /apps/devops/jenkins

1.3启动容器

docker run -itd -p 9003:8080 -p 9004:50000  --restart always -v /apps/devops/jenkins:/var/jenkins_home --name jenkins  jenkins/jenkins:lts

1.4打开Jenkins管理页面

http://IP:9003

1.5查看日志获取初始密码

docker logs -f jenkins

复制如下图中红框内的初始密码
当然,你也可以不通过日志查看,你可以进入黄色框中描述的文件查看初始密码也是一样的,二选一

1.6安装推荐的插件

如下图所示,左侧显示安装推荐的插件,右侧选择自定义安装插件。

我们选择安装推荐的插件,点击左侧的

如果全部都能正确安装,则会自动进入如下图界面

将信息输入对应输入框内,点击保存并完成,进入如下图所示

1.7成功安装Jenkins

默认,点击保存并完成,OK,这就算搭建成功了

2.配置Jenkins

2.1设置Jenkins时区为北京时间

点击系统管理——脚本命令行,输入脚本并运行,显示Result表示成功

System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')

2.2安装自动化构建和部署所需的插件

进入系统管理——插件管理,所需插件:【Maven Integration】、【Pipeline Maven Integration】、【Gitlab】、【Gitlab hook】、【SSH】、【Publish Over SSH】

插件全部安装完成后,可以重启一下Jenkins

2.3添加凭据

点击添加凭据——输入宿主机服务器的用户名和密码

2.4配置SSH remote hosts

这个配置是干什么的呢?配置SSH连接Dockerfile所在服务器的相关信息,并添加凭证,最后测试连接并保存,以备后面使用!!!

点击系统管理——系统设置

找到配置——下拉选择SSH remote hosts

如下图,输入对应的信息,并校验是否连接成功!成功后,点击应用——点击保存

2.5全局工具配置

由于我们要实现的是SpringBoot项目的自动化部署操作,所以需要安装JDK、Git、Maven、Docker

2.5.1安装JDK

可以安装多个,根据项目JDK版本需求

输入自定义JDK名称——勾选自动安装——输入Oracle账户、密码——选择JDK版本——勾选同意协议

2.5.2安装Git

输入自定义Git名称——勾选自动安装

2.5.3安装Maven

输入自定义名称——勾选自动安装——选择版本

2.5.4安装Docker

输入自定义名称——勾选自动安装

最后,点击应用——点击保存,OK,完成

那这些在什么时候才真正的安装了呢?

是在初次使用到JDK或Maven的时候,才会去自动安装

2.6全局安全配置

点击系统管理——全局安全配置

去掉防止跨站点请求伪造前的勾——点击应用——保存

2.7关于webhook

1.webhook网络钩子
	可以看成是一个callback  回调方法
	本回调方法核心即包含:
	    触发条件+可供触发的URL+密码(可选) 
	    触发条件为:push、merge、PR(即 New  Pull Request)等等git操作,
	    比如你提交一个push操作,就会触发URL请求,会以POST请求去请求这个URL。
		除此以外,你还可以自己指定这个POST请求的数据格式。(JSON,x-www-form-urlencoded等)。

2.webhook是gitlab端的
	触发webhook的条件,可以自行配置,都是本地对gitlab的git操作
	触发后去请求的URL地址,是Jenkins提供的。也就是触发后是去请求Jenkins的

3.而实现代码从gitlab到jenkins到自动部署,webhook就是gitlab和jenkins之间的关键点。
	后续会先配置jenkins,以获取到URL和Token,拿着这两个东西去gitlab配置webhook,即可。
	同时,webhook本身还会有很多的触发条件可以勾选。后续步骤可见!

3新建Jenkins任务

3.1点击新建任务,输入名称【本处输入名称注意】

【注意,本名称一般和项目名称一致,因为本名称会在jenkins工作空间下生成目录,类似于IDEA或Ecplise的工作空间的概念】

【所以,一般情况下,保证本名称=项目名称=docker镜像名称=docker容器名称 这样能尽可能的减轻jenkins配置的shell命令的复杂性!从而形成一定的规范!!】

选择构建一个Maven项目【因为是springboot的服务】

3.2源码管理

输入描述信息,源码管理选择Git,从gitlab复制克隆地址粘贴到Repository URL中,没有报错就表示OK的,(注意,这里我是克隆HTTP方式的地址,如果你是克隆SSH方式的地址,你需要添加Creadentials,配置个API Token就可以了)

3.3构建触发器

这里会获取到文章开始提到的URL和Token,这两个东西需要记录下来,供gitlab配置webhook使用

点击高级,拉下来找到Generate并点击,生成一串Secret Token:24d90d26b374ae2df2cda01c17338843(拿小本本记一下这个Token,等下跟上面的URL都会用到的)

3.4添加webhook

前往gitlab,进入要构建的项目,在setting中选择Integrations,输入URL和Secret Token 这两在上面图中已经给你标注了,去掉Enable SSL verification的勾选

根据自己的需求,勾选webhook的触发事件都有哪些

点击Add webhook,如图表示成功添加了webhook

3.5构建环境

勾选Add timestamps to the Console Output,等下可以看到控制台打印的信息,这个根据自己的需求勾选哈

3.6Pre Steps(构建之前的步骤)

本处选择是,执行shell,则表示本处配置的shell命令,是默认在jenkins容器中执行的,而不是在宿主机上

下拉选择执行 shell

在执行 shell的命令中输入以下命令,设置全局变量

SERVER_NAME_1=springboot
echo "=========================>>>>>>>工作空间WORKSPACE的地址:$WORKSPACE "
cd $WORKSPACE
echo "=========================>>>>>>>进入工作空间WORKSPACE,清除工作空间中原项目的工作空间$SERVER_NAME_1 "
rm -rf $SERVER_NAME_1
echo "=========================>>>>>>>清除工作空间中原项目的工作空间$SERVER_NAME_1 ......成功success"

注意:本处的SERVER_NAME_1=springboot 是配置项目的名称

3.7Build(构建)

我们是springboot项目,所以用到maven,这里设置一下全局操作,clean项目,并打成jar包,所以这里输入:

clean package -Dspring.profiles.active=jydd -Dmaven.test.skip=true

3.8Post Steps(执行任务)

只在jenkins构建成功后,才执行这一步

因为最后的构建成功的maven项目的jar包是以docker启动服务为目的,所以最后的docker操作,一定是在jenkins容器以外的服务器上运行的,可能是本机宿主机,也可能是远程的服务器,这个根据自己的情况去配置

本处选择,在远程的SSH执行shell脚本

选中只有构建成功才执行这些命令,然后选择Execute shell script on remote host using ssh

创建SSH执行命令,从创建文件夹和Dockerfile到docker容器运行

#=====================================================================================
#=================================定义初始化变量======================================
#=====================================================================================

#操作/项目路径(Dockerfile存放的路劲)
BASE_PATH=/usr/local/apps/jydd_api

# jenkins构建好的源jar路径  
SOURCE_PATH=/usr/local/apps/devops/jenkins/workspace

#【docker 镜像】【docker容器】【Dockerfile同目录下的jar名字[用它build生成image的jar]】【jenkins的workspace下的项目名称】
#这里都以这个命名[微服务的话,每个服务都以ms-springboot这种格式命名]
#注意统一名称!!!!!
SERVER_NAME=jydd_api

#容器id  [grep -w 全量匹配容器名] [awk 获取信息行的第一列,即容器ID]  [无论容器启动与否,都获取到]
CID=$(docker ps -a | grep -w "$SERVER_NAME" | awk '{print $1}')

#镜像id  [grep -w 全量匹配镜像名] [awk 获取信息行的第三列,即镜像ID]
IID=$(docker images | grep -w "$SERVER_NAME" | awk '{print $3}')

#源jar完整地址  [jenkins构建成功后,会在自己的workspace/项目/target 下生成maven构建成功的jar包,获取jar包名的完整路径]
#例如:/apps/devops/jenkins/workspace/springboot/target/springboot-0.0.1-SNAPSHOT.jar
#SOURCE_JAR_PATH=$(find "$SOURCE_PATH/$SERVER_NAME/target/"  -name "*$SERVER_NAME*.jar" )
SOURCE_JAR_PATH=/usr/local/docker/jenkins/workspace/jydd_api/yshop-api/target/jydd_api.jar

DATE=`date +%Y%m%d%H%M%S`


#=====================================================================================
#============================对原本已存在的jar进行备份================================
#=====================================================================================



# 备份
function backup(){
    if [ -f "$BASE_PATH/$SERVER_NAME.jar" ]; then
        echo "=========================>>>>>>>$SERVER_NAME.jar 备份..."
            mv $BASE_PATH/$SERVER_NAME.jar $BASE_PATH/backup/$SERVER_NAME-$DATE.jar
        echo "=========================>>>>>>>备份老的 $SERVER_NAME.jar 完成"

    else
        echo "=========================>>>>>>>老的$BASE_PATH/$SERVER_NAME.jar不存在,跳过备份"
    fi
}


#=====================================================================================
#============================  创建BASE_PATH  ================================
#=====================================================================================

function makedir(){
    if [ ! -d "$BASE_PATH" ]; then
         echo "=========================>>>>>>>>>>>$BASE_PATH 不存在,创建……"
             mkdir -p $BASE_PATH
         echo "=========================>>>>>>>>>>>$BASE_PATH 创建成功"
    else
         echo "=========================>>>>>>>>>>>$BASE_PATH 已存在,跳过创建"
    fi
}

#=====================================================================================
#============================  创建Dockerfile文件 ================================
#=====================================================================================

function createfile(){
      if [ ! -f "$BASE_PATH/Dockerfile" ]; then
             echo "======================>>>>>>>>>>>>>>>>>$BASE_PATH/Dockerfile 不存在,创建……"
                   cd $BASE_PATH
                   echo "FROM java:8" > Dockerfile
                   echo "MAINTAINER jw_tech" >> Dockerfile
                   echo "VOLUME /workspace" >> Dockerfile
                   echo "EXPOSE 8009" >> Dockerfile
                   echo "ADD $SERVER_NAME.jar /$SERVER_NAME.jar" >> Dockerfile
                   echo "ENTRYPOINT [\"java\",\"-Djava.security.egd=file:/dev/./urandom\",\"-Dspring.profiles.active=jydd\",\"-jar\",\"/$SERVER_NAME.jar\"]" >>Dockerfile
             echo "========================>>>>>>>>>>>>>>>>$BASE_PATH/Dockerfile 创建成功"
       else
             echo "=======================>>>>>>>>>>>>>>$BASE_PATH/Dockerfile 已存在,跳过创建"
       fi
}

#=====================================================================================
#=========================移动最新源jar包到Dockerfile所在目录=========================
#=====================================================================================


 
# 查找源jar文件名,进行重命名,最后将源文件移动到项目环境
function transfer(){
       
         
    echo "=========================>>>>>>>源文件完整地址为 $SOURCE_JAR_PATH"

        
    echo "=========================>>>>>>>重命名源文件"
        mv $SOURCE_JAR_PATH  $SOURCE_PATH/$SERVER_NAME/target/$SERVER_NAME.jar

    echo "=========================>>>>>>>最新构建代码 $SOURCE_PATH/$SERVER_NAME/target/$SERVER_NAME.jar 迁移至 $BASE_PATH"
        cp $SOURCE_PATH/$SERVER_NAME/target/$SERVER_NAME.jar $BASE_PATH 

    echo "=========================>>>>>>>迁移完成Success"

}
 


#=====================================================================================
#==================================构建最新镜像=======================================
#=====================================================================================


 
# 构建docker镜像
function build(){
    
    #无论镜像存在与否,都停止原容器服务,并移除原容器服务
    echo "=========================>>>>>>>停止$SERVER_NAME容器,CID=$CID"
    docker stop $CID

    echo "=========================>>>>>>>移除$SERVER_NAME容器,CID=$CID"
    docker rm $CID

    #无论如何,都去构建新的镜像
    if [ -n "$IID" ]; then
        echo "=========================>>>>>>>存在$SERVER_NAME镜像,IID=$IID"


        echo "=========================>>>>>>>移除老的$SERVER_NAME镜像,IID=$IID"
        docker rmi $IID

        echo "=========================>>>>>>>构建新的$SERVER_NAME镜像,开始---->"
        cd $BASE_PATH
        docker build -t $SERVER_NAME .
        echo "=========================>>>>>>>构建新的$SERVER_NAME镜像,完成---->"

    else
        echo "=========================>>>>>>>不存在$SERVER_NAME镜像,构建新的镜像,开始--->"


        cd $BASE_PATH
        docker build -t $SERVER_NAME .
        echo "=========================>>>>>>>构建新的$SERVER_NAME镜像,结束--->"
    fi
}
 

#=====================================================================================
#==============================运行docker容器,启动服务===============================
#=====================================================================================


# 运行docker容器
function run(){
    backup
    makedir
    createfile
    transfer
    build

    docker run --name $SERVER_NAME -itd  -e TZ=Asia/Shanghai --network myNetwork --ip 172.18.0.10  $SERVER_NAME

}
 
#入口
run

OK,到这里基本的任务已经新建成功,至于后续的两个步骤,根据自己的需求自行配置

点击应用,保存

3.9测试

测试push事件触发自动化构建和部署

前往gitlab,刚我们新增的webhook,点击test下拉选择push events,出现HTTP 200表示OK了

回到Jenkins可以看到任务列表,进入任务列表中的springboot,可以看到构建历史

至此,我们的自动部署就已经完成!

4参考资料

https://blog.csdn.net/cjiankai/article/details/98213024