一、相关概念介绍:
持续(Continuous):不断地获取反馈、响应反馈
集成(Integration):编译、打包、测试
部署(Deployment):应用组件或基本设施的代码或配置变更在产品环境生效
发布(Release):具有业务影响的功能变化对最终用户可见
交付(Delivery):可以理解为从Deployment到Release之间的阶段,强调的是一种能力,开发有能力频繁部署,业务有能力随时发布
持续集成
持续集成(Continuous Integration简称CI)是利用一系列的工具、方法与规则,做到快速的构建代码,并自动的进行测试,从而提高代码的效率和质量.
大致的步骤如下:
开发人员通过IDE工具将代码推送到gitlab.
jenkins从gitlab中获取到源码,并使用maven编译、打包、自动构建镜像.
jenkins在构建脚本中调用docker命令将构建好的镜像push到本地Docker Registry.并启动相应的容器.
jenkins构建失败或者成功,可以及时将结果推送给相关人员,比如测试人员,安排测试.
运维人员只需获取相应的镜像就可以快速发布到生产环境.
Jenkins:开源的、可扩展的、基于Web界面的持续集成平台
Git:开源的分布式版本控制系统
GitLab:用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务
Maven:基于项目对象模型(POM)的项目管理及自动构建工具,用于编译源码并打包
Nexus:Maven私服
SonarQube:用于代码质量管理和检测的开源平台
环境搭建
本地开发环境为windows环境,开发工具为IntelliJ IDEA.
1.本地下载并安装配置git客户端Git-2.14.1-64-bit
2.在虚拟机上搭建gitlab服务
拉取gitlab镜像
[root@bogon/]# docker pull gitlab/gitlab-ceUsingdefaulttag:latestlatest
启动gitlab容器
[root@bogon/]# docker run--detach \>--hostname gitlab.william.com \>--publish8443:443--publish48080:80--publish8022:22\>--name gitlab \>--restart always \>--volume/opt/gitlab/config:/etc/gitlab \>--volume/opt/gitlab/logs:/var/log/gitlab \>--volume/opt/gitlab/data:/var/opt/gitlab \>gitlab/gitlab-ce:lateste19375a8f2b2a76e6dae2ecd5e7b0d5864c7a2e9975bfc4274cb166cd5091b7b
注意上面的docker run命令指定了域名为gitlab.william.com,必须通过该域名才能访问gitlab,所以在gitlab容器启动前要先在虚拟机和本地配置ip与域名的映射关系.
#在linux下: vi /etc/hosts #在windows下: cd C:\Windows\System32\drivers\etc\hosts
修改host文件在最下面添加
192.168.56.101 gitlab.william.com
另外我们指定了三个端口,22表示ssh端口,80表示http端口,443表示https端口,分别映射到宿主机上的8022、48080和8443端口,我们还通过--volume指定目录映射,其中
/etc/gitlab表示gitlab的配置目录,映射到宿主机的/opt/gitlab/config目录.
/var/log/gitlab表示gitlab的日志目录,映射到宿主机的/opt/gitlab/logs目录.
/var/opt/gitlab表示gitlab的数据目录,映射到宿主机的/opt/gitlab/data目录.
启动gitlab容器后打开浏览器输入地址http://gitlab.william.com:48080发现访问不了
先查看48080端口是否开启
[root@bogon/]# firewall-cmd--zone=public--query-port=48080/tcpno
很明显需要开启48080端口
[root@bogon/]# firewall-cmd--zone=public--add-port=48080/tcp--permanentsuccess[root@bogon/]# firewall-cmd--reloadsuccess
再次打开浏览器输入地址http://gitlab.william.com:48080后重定向进入修改管理员密码页面,我们将密码修改为12345678.
修改完密码后接着进入管理登录页面,输入登录用户名密码root/12345678登录进去.
接下来新建一个空的项目hello,其中hello为项目名称,可设置可见性级别:
Private表示私有项目,授予具体权限的用户才能访问.
Internal表示内部项目,可登陆的用户都能克隆项目.
Public表示公开项目,没有任何权限的用户都能克隆项目.
项目创建完毕之后,开始进入主页面:
接着我们需要做的就是将本地java代码推送至gitlab中.
在推送之前先全局设置git
[root@bogon /]# git config --global user.name"william.zhang"
[root@bogon /]# git config --global user.email"952408421@qq.com"
3.使用IntelliJ IDEA 将项目发布(提交)到GitLab
首先需要启用项目的版本管理功能,点击VCS 启用版本控制.
然后右击项目,选择Git->add,将项目中的文件加入到git add中等待本地提交,add 后的文件都会由橙色变成绿色.
下一步本地提交代码,右击项目选择Git->Commit Directory...这时本地提交成功,可以看见文件颜色从绿色变成了黑色.
最后就是将代码push到远程git仓库了,右击项目 Git->Repository ->Push
在Define Remote窗口里面的URL中填入http://gitlab.william.com:48080/root/hello.git
点击ok按钮弹出下面窗口
输入用户名密码:root/12345678
然后开始push...
push成功之后刷新http://gitlab.william.com:48080/root/hello可以看到本地代码已经推送至gitlab了.
4.安装jenkins
拉取jenkins镜像
[root@bogon~]# docker pull jenkinsci/jenkinsUsingdefaulttag:latestlatest:Pullingfromjenkinsci/jenkins
然后开启38080端口,并启动jenkins容器.
[root@bogon~]# docker run \>-d \>-p38080:8080\>-p50000:50000\>--name jenkins \>--link gitlab:gitlab.william.com \>-u root \>-v/opt/jenkins:/var/jenkins_home \>jenkinsci/jenkins:latestf7fa42d4e010833da5d9e5258855ac53d7d1c4855549e12992ceac236f3d583a
其中8080端口是jenkins的端口,38080是映射宿主机的端口,50000端口是master和slave通信端口.以root用户来启动容器,同时通过配置--link连接gitlab,因为要与gitlab容器通讯下载代码.
打开浏览器http://192.168.56.101:38080/访问跳转到解锁jenkins页面.
在服务器上以下执行命令查看密码
[root@bogon~]# cat/var/jenkins_home/secrets/initialAdminPasswordcat:/var/jenkins_home/secrets/initialAdminPassword:没有那个文件或目录
由于之前启动jenkins容器时我们做了目录映射 -v /opt/jenkins:/var/jenkins_home,所以要将执行命令改为:
[root@bogon~]# cat/opt/jenkins/secrets/initialAdminPasswordaa42541900b146f59007de7c0cdc4d3a[root@bogon~]#
在解锁页面上输入上述密码,继续进入以下页面:
建议选择安装推荐的插件,基本上一些常用的插件都会被安装,安装过程如图:
安装完后进入以下页面:
单击开始使用Jenkins按钮进入jenkins系统,点击左侧菜单中的系统管理进入Jenkins管理模块,查看系统设置:
主目录是存放Jenkins所有的文件的,工作空间根目录和构建记录目录默认都是在Jenkins主目录下,这个设置一般不用进行变更.
执行者数量:可以并发构建的数量.
标记:用来记录这个机器的名称(为了分配节点使用,后面子节点会详细介绍).
用法:设置这个节点的执行策略(包括尽可能使用这个节点和只允许绑定到这台机器的job.
生成前等待时间:这个时间为构建开始前的等待时间.
scm签出重试次数:使用svn或者git拉取代码失败重试的次数.
Restrict project naming:限制项目命名,勾选后可以看到具体设置,可以设置为默认或者使用正则表达式进行限制.
全局属性
environment variables:设置全局变量,在这里定义的全局变量可以在构建或者发送邮件时引用.
tool locations:设置全局工具,可以把需要的工具都在这里进行配置,比如maven,ant,jdk等.
设置时间格式
管理监控默认选中所有
jenkins location
jenkins url :设置jenkins的url(发送邮件引用jenkins的地址会取这个值,如果设错了,邮件的连接就会打不开)
系统管理员邮件地址:管理员的邮件地址(在构建需要发送邮件时,会用到这个邮件地址)
接着进入插件管理,选择可选插件板块,安装并配置maven插件,如果缺少Maven Integration Plugin插件,在创建job时,不会有新建一个maven项目选项.
接下来使用jenkins创建一个构建任务.
输入项目名称hello,选中构建一个maven项目点击确定按钮进入项目配置页面:
在源码管理板块中我们选择git并在repository url填写git仓库名称,但此时会报错:
从报错提示中发现jenkins访问gitlab.william.com时出现连接拒绝,可以断定是由于jenkins容器与gitlab容器无法通讯导致的.
解决方法是在启动jenkins容器时添加--link选项,并将其指定到需要连接的gitlab容器,重启jenkins容器后重新填写仓库URL出现另一个错误:
通过错误提示可知:我们所填入的URL是需要身份认证的,可单击Credentials下拉框右侧的Add按钮,并选择Jenkins选项,弹出身份认证信息对话框:
上面填写的是gitlab的用户名密码验证,添加完后需要选中它,这个时候可以看到已经不报错了.
紧接着我们在build板块中配置maven:
在Goals and options使用clean package -q可以加快maven构建速度.
添加构建后操作
点击增加构建后操作步骤,选择归档成品,在文本框中输入需要存档的文件路径:**/target/*.jar.
单击保存回到主界面
单击左侧菜单的立即构建并在控制台输出中查看构建日志:
由日志可看出构建过程报错了提示找不到pom文件,根据提示回到build板块中修改maven配置Root POM为hello/pom.xml,再重新手工构建即可.
构建完成后,回到jenkins主界面可以看到构建任务列表
小球图标表示构建状态,蓝色表示构建成功,但我们的目的是搭建一个持续集成的环境,在开发阶段我们会不断的推送代码到gitlab,所以我们需要利用jenkins来帮我们实现自动构建发布.
在Post step板块中填写shell脚本实现自动化发布.
#定义变量API_NAME="hello"API_VERSION="1.0.0"API_PORT=58080IMAGE_NAME="192.168.56.101:5000/hello/$API_NAME:$BUILD_NUMBER"CONTAINER_NAME=$API_NAME-$API_VERSION#进入target目录复制Dockerfile文件cd $WORKSPACE/$API_NAME/targetcp classes/Dockerfile .#构建docker镜像docker build -t $IMAGE_NAME .#推送docker镜像docker push $IMAGE_NAME#删除docker容器cid=$(docker ps | grep "$CONTAINER_NAME" | awk '{print $1}')if [ "$cid" != "" ]; then docker rm -f $cidfi#启动docker容器docker run -d -p $API_PORT:8080 --name $CONTAINER_NAME $IMAGE_NAME#删除Dockerfile文件rm -f Dockerfile
再次点击立即构建按钮
出现构建失败错误docker not found,说明jenkins容器中无法执行docker命令,网上搜了一下,主要解决方案有以下几种:
1.不使用Jenkins镜像,直接在宿主机上安装Jenkins服务,可以调用宿主机上的docker命令.
2.使用dood方案:表示在docker容器中使用宿主机上的docker服务.
3.使用dind方案:在docker镜像中要再安装docker服务,此时在容器中的docker和宿主机的docker是两个不同的程序,相互没有关联.
4.使用https与docker后台程序通讯,通过https暴露socket,并且可以使用宿主的镜像,但因为打开了端口增加了攻击面,可以说是最不安全的.
下面我们使用第2种方案即dood来解决这个问题.
1.先删掉之前建好的jenkins容器和镜像,然后在虚拟机上创建一个空的Dockerfile文件.
[root@bogon jenkins-dood]# touch Dockerfile
2.编写Dockerfile脚本
[root@bogon jenkins-dood]# vi Dockerfile
FROM jenkins:latestUSER rootARG dockerGid=999RUN echo "docker:x:${dockerGid}:jenkins" >> /etc/groupUSER jenkins
3.重新构建jenkins镜像
[root@bogon jenkins-dood]# docker build-t jenkins.
4.在启动Jenkins容器时,我们需要先创建一个Jenkins的配置目录,并且挂载到docker 里的Jenkins目录下.
[root@bogon/]# mkdir-p/opt/jenkins-dood
5.修改目录权限.
[root@bogon/]# chown-R1000/opt/jenkins-dood
6.开始运行jenkins容器
[root@bogon/]# docker run \>-d \>-p38080:8080\>-p50000:50000\>--name jenkins \>-v/var/run/docker.sock:/var/run/docker.sock \>-v $(which docker):/bin/docker \>-v/opt/jenkins-dood:/var/jenkins_home \>-u root \>--link gitlab:gitlab.william.com \>jenkins:latesta5904b8c7f50234b52c3772ab13cca4d61f02cb887e0524ff4f6cf53bb63b501
注意这两个-v参数(将jenkins容器内的docker命令指向了宿主机):
-v /var/run/docker.sock:/var/run/docker.sock
-v $(which docker):/bin/docker
之后直接在jenkins里面就可以使用docker命令了.同样的启动jenkins容器后找回管理员密码:
cat /opt/jenkins-dood/secrets/initialAdminPasswordd1291723c28848cda642d8ba8351e439
进去系统后先修改jenkins时间设置:打开【系统管理】->【脚本命令行】运行下面的命令:
System.setProperty('org.apache.commons.jelly.tags.fmt.timeZone', 'Asia/Shanghai')
其他的配置步骤跟我们之前配置的一样.编写完自动部署脚本之后,我们同样执行立即构建,这个时候报错了:
根据错误日志提示可知:找不到libltdl.so.7这个文件,网上搜了一下,在jenkins容器启动命令增加文件映射-v /usr/lib/x86_64-linux-gnu/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7.重新构建,这次报另一个错误:
原因是centos7上没有装libltdl.so.7这个library,我们通过下面这个命令来安装:
[root@bogon /]# yum install libltdl.so.7
安装完之后找到安装的位置:/usr/lib64/libltdl.so.7,接着再重启jenkins容器:
[root@bogon/]# docker run \>-d \>-p38080:8080\>-p50000:50000\>--name jenkins \>-v/var/run/docker.sock:/var/run/docker.sock \>-v $(which docker):/bin/docker \>-v/opt/jenkins-dood:/var/jenkins_home \>-v/usr/lib64/libltdl.so.7:/usr/lib/x86_64-linux-gnu/libltdl.so.7>-u root \>--link gitlab:gitlab.william.com \>jenkins:latest
再次执行jenkins构建,这回构建成功了,执行docker images查看一下jenkins自动部署的镜像.
[root@bogonbin]# docker imagesREPOSITORYTAGIMAGEIDCREATEDSIZE192.168.56.101:5000/hello/hello9231daf17317c18hours ago673MB192.168.56.101:5000/hello/hello7c9b2c721e7e118hours ago673MB192.168.56.101:5000/hello/hello629b676b8d27319hours ago673MB192.168.56.101:5000/hello/hello5f1bdfbf7977e20hours ago673MBjenkins latest cfa26ddfdfaa24hours ago696MBgitlab/gitlab-ce latest d87e1ba8aa5f7days ago1.46GB192.168.56.101:5000/hello/hello-api1.0.068bbcea2575f7days ago673MBnginx latest c8252167658013days ago109MBjenkins<none>cd14cecfdb3a2weeks ago696MBregistry latest b2b03e9146e14weeks ago33.3MBjava8d23bdf5b1b1b18months ago643MB
测试jenkins自动发布的容器是否正常运行
[root@bogonbin]# curl http://192.168.56.101:58080/hello/hihi
[root@bogonbin]#
返回结果为"hi",说明jenkins已经可以正常从gitlab中获取源码来构建生成docker镜像并以docker容器的方式进行发布,供生产环境使用了.但目前还是以手动的方式来执行构建任务,我们真正需要的是一款自动化的发布平台,在开发人员将源代码推送至gitlab后自动触发jenkins构建任务,再次打开构建配置,回到构建触发器配置:
选中Poll SCM,Poll SCM表示定时检查源码变更(根据SCM软件的版本号),如果有更新就checkout最新code下来,然后执行构建动作.如果需要每隔30分钟检查一次源码变化,有变化就执行则可以在日程表中输入一个基于CRON表达式,比如:H/30 * * * *表示每30分钟执行一次构建.我们来测试一下,在idea中修改测试代码将原来的返回值"hi"改为"hello world",然后push到gitlab中,观察jenkins是否会自动构建.
从上图中我们可以看到jenkins已经开始自动构建了.
最后再来验证下自动化发布的结果.
[root@bogonbin]# curl http://192.168.56.101:58080/hello/hihello world[root@bogonbin]#
返回结果为"hello world"说明jenkins已经成功自动构建并部署了.
参考资料:
https://www.jianshu.com/p/ee4a2a9e7e30
https://www.2cto.com/net/201909/816570.html
https://www.jianshu.com/p/b1f856646296