前面我们搭建好了基本的jenkins环境,是时候借助jenkins的构建任务将推送到gitlab的项目源码拉取过来进行基础的CI构建了。开干!
gitlab创建项目
spring boot项目
首先我们在本地用idea向导创建一个基于gradle构建的spring boot项目:
项目路径:E:\study\spring_boot\code\cicd\hello\hello
这是一个最简单的hello world应用,代码就省略了。
创建gitlab项目
登录gitlab后,New Project -> 创建一个空白项目
点创建项目即可。
git客户端
安装与设置
安装向导中,勾选添加到桌面,选择editor:
后续安装默认即可。
全局设置用户、邮箱,在终端中运行:
git config --global user.name "xiaojuan"
git config --global user.email "1372569394@qq.com"
生成和配置key
桌面右键
执行操作命令:
# 进入用户目录
cd ~/
# 创建.ssh目录
mkdir .ssh
cd .ssh
# 键入下面的命令后点几次回车
ssh-keygen -t rsa -C "1372569394@qq.com"
把id_rsa.pub里的内容粘贴到gitlab密钥中
进入项目首页
进入地址:http://192.168.0.113:8929/-/profile/keys
点击Add Key。
commit和push源码
使用idea自带的git工具进行图形化的操作。
创建本地仓库
选中hello项目,项目右键 -> Git -> 提交目录
全部勾选,写下提交信息,点提交
接下来进行push操作,先在gitlab项目页clone下,地址:ssh://git@192.168.0.114:2224/root/hello.git
项目右键-> Git -> Push
点Define remote,输入URL:ssh://git@192.168.0.114:2224/root/hello.git
最后直接点push按钮即可。
这样看到最终把项目push到gitlab上了。
后续改了代码可以commit并push:
基础CI流程
配置全局凭据
先配置全局jenkins用户的ssh登录凭据
把本地.ssh目录下的id_rsa文件内容拷贝到private key的填写域中。
同时配置在全局安全策略中不验证host key
创建任务拉取代码
在Jenkins的Dashboard页面左侧点新建任务,输入任务名test01,选自由风格的任务,确定。
添加git仓库地址:
最后保存。
然后点立即构建,看到控制台输出,拉取到gitlab仓库中项目的最新代码:
进入jenkins容器的内部查看下拉取的源码目录:
[root@dev-1 jenkins]# docker exec -it jenkins bin/bash
执行gradle构建
找到任务的项目配置:
设置完点击保存。
构建后,输出的信息:
推送可执行jar
继续将gradle构建好的可执行jar包推送到实现配置好的服务器test-1上。
注意,这里推送后的路径要删除前缀的路径,因为我们不希望在服务器上也创建这样的目录。
远程部署和启动应用
要执行spring boot的远程构建,我们可以先通过jenkins构建后把构建好的jar包传到目标服务器,在把要执行的docker相关的命令也传过去,进行执行。现在我们将采用另一种方式,通过在工程中增加gradle的docker插件来直接支持远程打包,在目标服务器上生成构建好的image,然后再发送启动容器的命令,把目标服务启动起来。
gradle的docker插件
首先在工程中增加如下gradle的docker插件配置:
plugins {
...
id 'com.bmuschko.docker-spring-boot-application' version '6.7.0'
}
...
docker {
url = 'tcp://192.168.0.115:2375'
springBootApplication {
baseImage = 'openjdk:8-jre-slim'
maintainer = 'xiaojuan'
ports = [8082]
images = "hello:${PROJECT_VERSION}"
jvmArgs = ['-Dspring.profiles.active=test']
}
}
...
然后刷新gradle后,看到要执行的目标任务:
远程docker服务设置
执行会发现,目标服务拒绝请求,这里要修改下远程服务器的docker中的配置:
在服务器中打开文件:/lib/systemd/system/docker.service,修改的内容:
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
重启下docker
systemctl daemon-reload
systemctl restart docker
确保本地可以执行下面命令:
curl 192.168.0.115:2375
{"message":"page not found"}
dockerBuildImage任务
先在目标服务器上pull基础镜像:
docker image pull daocloud.io/library/java:8u40-jdk
然后执行dockerBuildImage任务,可以看到目标服务器上构建好的image:
当修改了源码后,重新构建后,会发现生成新的image,而原来的image变为废弃的null,这些是我们考虑要清理的。
提交修改后的build.gradle的代码,进行Jenkins的构建,修改gradle要执行的目标任务:
可以看到gradle构建的目标的任务:
说明Jenkins的构建任务执行了docker远程构建image的插件任务。
启动服务
这里我们将通过docker-compose来启动spring boot应用,先在工程中增加docker-compose.yml的定义:
提交git后,修改Jenkins中hello项目构建任务的配置,ssh传输设置改为如下,舍弃原来传jar包的方式:
再执行下Jenkins的构建,看到最终在test-1服务器上构建了image(如果代码有更新的话,会重新构建image),同时会把工程中的docker/docker-compose.yml文件传到基准路径/usr/local/test下的hello/下。如果这个docker-compose后续不经常改,也可以手动在test-1上建下,不要维护到git上,每次jenkins拉取后都要执行后续的传文件,就没这个必要了,只要关注服务的重新启动。再看下我们要对远程服务器执行的构建命令:
这样我们就可以对有变更的构建重启服务了,并且会把作废的image清理掉。
基于tag的构建
在我们的代码库中通常我们会以打tag的形式来标注一个项目或者模块当前开发的功能版本分支,同样在jenkins构建和部署应用时也要能对特定的tag所代表的分支进行构建。这一小节,一起来实践下。
Jenkins参数化构建设置
选择参数化构建:
在gradle构建之前,增加执行shell的步骤:
把新增的shell框挪到gradle构建之前,
最后保存
设置gitlab tag
这样在每次改了代码提交后,可以在新的时间点上设置新的tag。
维护gradle构建的版本
gitlab上打的标签,在jenkins中执行构建时,可以从环境参数获取git参数传过来的信息,也就是这里的tag参数:
build.gradle中获取环境参数:
ext.PROJECT_VERSION = System.getenv('tag')
docker-compose.yml中获取环境参数:
...
services:
hello:
image: hello:${tag}
...
按指定tag的版本启动服务
当gradle的docker插件按tag打出版本后,要在目标服务器上启动相应版本的应用,这里需要在docker-compose up时指定一个tag相关的环境变量,而在jenkins服务器发送命令时,可以这样传递环境变量:
对于同一个tag,如果要更新功能,可以先在gitlab上删除tag,提交代码后重新再打相同的tag,再jenkins构建该tag,此时docker image prune -f会清理废弃的image。
Jenkins构建时指定源码的tag版本即可: