🔜什么是Jenkins?🔚
Jenkins是一款基于Java开发的开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。Jenkins提供多种安装方式,提供超过1000个插件来满足任何项目的需要。
Jenkins的特征:
开源的Java语言开发持续集成工具,支持持续集成,持续部署。 易于安装部署配置:可通过yum安装,或下载war包以及通过docker容器等快速实现安装部署,可方便web界面配置管理。 消息通知及测试报告:集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知,生成JUnit/TestNG测试报告。 分布式构建:支持制Jenkins能够让多台计算机一起构建/测试。 文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等。 丰富的插件支持:支持扩展插件,你可以开发适合自己团队使用的工具,如git,svn,maven,docker等。
本文通过GitLab+Jenkins+Tomcat,构建CI/CD流程。
主机规划
主机名
ip
所需软件
用途
121
192.168.1.121
GitLab-12.4.2
代码托管
124
192.168.1.124
Jenkins、JDK-21、Maven-3.9.9、 Git、SonarQube
Jenkins持续集成
125
192.168.1.125
JDK-1.8、Tomcat-8.5
发布测试
服务器操作系统为centos7.9
部署步骤 部署GitLab 安装GitLab 安装依赖
1 yum -y install policycoreutils-python policycoreutils postfix
下载并安装gitlab
1 2 3 4 # 下载gitlab安装包 curl -O http://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-12.4.2-ce.0.el7.x86_64.rpm # 安装gitlab rpm -i gitlab-ce-12.4.2-ce.0.el7.x86_64.rpm
修改gitlab默认访问端口
1 2 3 4 5 vi /etc/gitlab/gitlab.rb # 将默认端口80修改为82 external_url "http://192.168.1.121:82" nginx['listen_port'] = 82
重载配置,启动gitlab
1 2 gitlab-ctl reconfigure gitlab-ctl restart
配置防火墙策略
1 2 3 firewall-cmd --add-port=82/tcp --permanent firewall-cmd --reload firewall-cmd --list-all
在浏览器中输入http://192.168.1.121:82/,修改root用户密码,并用root用户登录gitlab
管理GitLab (1)创建组
使用管理员root创建组,一个组里面可以有多个项目分支,可以将开发添加到组里面进行设置权限,不同的组就是公司不同的开发项目或者服务模块,不同的组添加不同的开发即可实现对开发设置权限的管理。
(2)创建项目
(3)创建用户
在管理中心-概览-用户中,创建一个新用户test1
,并设置密码,将用户加入刚创建的项目中。
Gitlab用户在组里面有5种不同权限:
Guest:可以创建issue、发表评论,不能读写版本库
Reporter:可以克隆代码,不能提交,QA、PM可以赋予这个权限
Developer:可以克隆代码、开发、提交、push,普通开发可以赋予这个权限
Maintainer:可以创建项目、添加tag、保护分支、添加项目成员、编辑项目,核心开发可以赋予这个权限
Owner:可以设置项目访问权限Visibility Level、删除项目、迁移项目、管理组成员,卉发组组长可以赋予这个权限
上传项目代码
使用idea创建java项目,并上传至gitlab仓库
本文中使用的java项目代码,源自b站up主,’’涣沷a靑惷’’,原文链接为: https://www.yuque.com/huanfqc/jenkins/jenkins。
java代码地址为: https://share.feijipan.com/s/qdEO7czl
将项目导入idea中,并配置gitlab相关设置,推送代码,具体步骤参考上面提到的原文链接。
部署Jenkins
安装jenkins-2.19*版本时,无法正常安装中文插件。本文使用的jdk为jdk-21、jenkins为2.492.3,且均为rpm方式安装
(1)安装jdk
1 2 3 4 yum install -y wget && wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.rpm rpm -ivh jdk-21_linux-x64_bin.rpm # 查看版本 java -version
(2)安装Jenkins
1 2 3 4 # 下载jenkins curl -O https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat-stable/jenkins-2.492.3-1.1.noarch.rpm # 安装 rpm -ivh jenkins-2.492.3-1.1.noarch.rpm
(3)修改jenkins的配置文件
1 2 3 4 5 vi /etc/sysconfig/jenkins # 修改默认用户为root JENKINS_USER="root" # 修改默认端口为8888 JENKINS_PORT=8888
(4)配置防火墙策略,并启动jenkins
1 2 3 4 5 6 7 firewall-cmd --add-port=8888/tcp --permanent firewall-cmd --reload firewall-cmd --list-all # 启动jenkins systemctl daemon-reload systemctl start jenkins systemctl enable jenkins
(5)查看jenkins的admin初始化密码
1 cat /var/lib/jenkins/secrets/initialAdminPassword
(6)在浏览器中输入http://192.168.1.124:8888/访问,输入admin初始化密码。
(7)点击选择插件来安装
,选择无
,跳过安装插件,为之后重新配置下载插件的国内源做准备。
(8)按引导完成jenkins的安装。
配置国内插件源 (1)选择左侧边栏中的Jenkins -Manage Jenkins-Manage Plugins,选择Available,等待插件相关文件的加载。
(2)进入插件的目录,将地址修改为国内源
1 2 3 cd /var/lib/jenkins/updates && ll sed -i 's|http://updates.jenkins-ci.org/download|https://mirrors.tuna.tsinghua.edu.cn/jenkins|g' default.json sed -i 's|http://www.google.com|https://www.baidu.com|g' default.json
(3)访问jenkins,选择左侧边栏中的Jenkins -Manage Jenkins-Manage Plugins,选择Advanced,把Update Site改为https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
(或者https://mirrors.huaweicloud.com/jenkins/updates/update-center.json
),保存,在浏览器中输入http://192.168.1.124:8888/restart
,点击并重启jenkins。
设置中文 安装中文插件,选择左侧边栏中的Jenkins -Manage Jenkins-Manage Plugins,选择Advanced,搜索chinese
,勾选插件,并点击下载并重启。
管理用户权限 安装Role-based Authorization Strategy
插件,管理用户权限。安装完成后,(新版jenkins)选择Manage Jenkins-Security,授权策略选择Role-Based Strategy。选择Manage Jenkins-Manage and Assign Roles,进行角色的创建和分配管理。
凭证管理 (1)安装Credentials Binding
插件,进行凭证管理。
凭证类型:
Username with password:用户名和密码
SSH Username with private key:使用ssH用户和密钥
Secret file:需要保密的文本文件,使用时Jenkins会将文件复制到一个临时目录中,再将文件路径设置到一个变量中,等构建结束后,所复制的Secret file就会被删除。
Secret text:需要保存的一个加密的文本串,如钉钉机器人或Github的api token
Certificate:通过上传证书文件的方式
常用的凭证类型有:Username with password(用户密码)和SSH Username with private key(SSH密钥)
(2)安装git
插件,并在服务器上下载git。
密码凭证 (1)创建jenkins项目和密码凭证。选择Manage Jenkins-Credentials,点击全局
-Add Credentials
,添加gitlab用户test1的用户名和密码,创建凭证。
(2)创建一个新任务test01
,点击配置,设置源码管理为Git,填写gitlab的项目仓库地址(http开头),选择test1的凭证,保存即可。
(3)进入test01,点击Build Now,等待任务构建完成后,点击控制台输出查看详细信息。
SSH密钥凭证 (1)在jenkins服务器中创建SSH密钥。
1 2 3 4 5 6 7 ssh-keygen -t rsa # 查看公钥内容 cat ~/.ssh/id_rsa.pub # 测试 SSH 连接 ssh -T git@192.168.1.121 # 查看是否有gitlab主机,确保有该主机,否则使用ssh凭证时会报错 cat ~/.ssh/known_hosts
(2)使用管理员账户登录Gitlab,选择设置
-SSH密钥
,填入SSH公钥内容,并保存。
(3)在服务器中使用命令cat ~/.ssh/id_rsa
,查看私钥内容。在jenkins中创建SSH密钥凭证,输入用户名root和SSH私钥内容,保存即可。
(4)创建一个新任务test02
,点击配置,设置源码管理为Git,填写gitlab的项目仓库地址(git开头),选择SSH凭证,保存即可。
(5)进入test02,点击Build Now,等待任务构建完成后,点击控制台输出查看详细信息。
安装Maven (1)下载安装Maven
1 2 3 4 5 6 7 8 9 10 11 curl -O https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.9.9/binaries/apache-maven-3.9.9-bin.tar.gz # 创建存储目录 mkdir -p /opt/maven tar -vxzf apache-maven-3.9.9-bin.tar.gz -C /opt/maven/ # 配置环境变量,使环境生效 echo " export MAVEN_HOME=/opt/maven/apache-maven-3.9.9 export PATH=\$PATH:\$MAVEN_HOME/bin" >> /etc/profile source /etc/profile # 查看maven版本 mvn -v
(2)配置jenkins与maven关联
在Manage Jenkins-Tools中配置JDK安装
和Maven安装
,配置其对应安装路径。
在Manage Jenkins-System-全局属性中,新增3个Environment variables
。
(3)修改Maven的本地仓库位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 创建本地仓库 mkdir -p /data/jenkins/repo # 修改Maven的配置文件 vi /opt/maven/apache-maven-3.9.9/conf/settings.xml # 将<localRepository>/path/to/local/repo</localRepository>修改为 <localRepository>/data/jenkins/repo</localRepository> # 在<id >maven-default-http-blocker</id>所在的镜像后添加阿里云镜像源 # <mirror> # <id >maven-default-http-blocker</id> # <mirrorOf>external:http:*</mirrorOf> # <name>Pseudo repository to mirror external repositories initially using HTTP.</name> # <url>http://0.0.0.0/</url> # <blocked>true </blocked> # </mirror> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> <mirrorOf>central</mirrorOf> </mirror>
(4)测试Maven配置
在jenkins中选择任务test02
,选择配置-Environment-Build Steps,选择Execute shell中输入命令mvn clean package
,保存后,点击Build Now,等待任务构建完成后,点击控制台输出查看详细信息。
此时服务器上的test02任务目录中会新增一个target
目录。
[root@124 workspace]# ls test01 test01@tmp test02 test02@tmp [root@124 workspace]# cd test01 [root@124 test01]# ls pom.xml src [root@124 test01]# cd .. [root@124 workspace]# ls test01 test01@tmp test02 test02@tmp [root@124 workspace]# cd test02 [root@124 test02]# ls pom.xml src target [root@124 test02]# pwd /var/lib/jenkins/workspace/test02 [root@124 test02]#
安装Tomcat 下载jdk-1.8和tomcat-9
1 2 3 4 5 6 7 8 yum install -y java-1.8.0-openjdk* curl -O https://mirrors.huaweicloud.com/apache/tomcat/tomcat-9/v9.0.104/bin/apache-tomcat-9.0.104.tar.gz # 创建存储目录 mkdir -p /opt/tomcat/ # 解压 tar -zxvf apache-tomcat-9.0.104.tar.gz -C /opt/tomcat/ # 启动tomcat /opt/tomcat/apache-tomcat-9.0.104/bin/startup.sh
配置防火墙策略
1 2 3 firewall-cmd --add-port=8080/tcp --permanent firewall-cmd --reload firewall-cmd --list-all
在浏览器中访问http://192.168.1.125:8080/
。
配置tomcat的用户角色
1 2 3 4 5 6 7 8 9 10 11 12 13 vi /opt/tomcat/apache-tomcat-9.0.104/conf/tomcat-users.xml <role rolename ="tomcat" /> <role rolename ="role1" /> <role rolename ="manager-script" /> <role rolename ="manager-gui" /> <role rolename ="manager-status" /> <role rolename ="admin-gui" /> <role rolename ="admin-script" /> <user username ="tomcat" password ="tomcat" roles ="manager-gui,manager-script,tomcat,admin-gui,admin-script" />
配置tomcat的远程访问地址范围
1 2 3 4 5 vi /opt/tomcat/apache-tomcat-9.0.104/webapps/manager/META-INF/context.xml <Valve className ="org.apache.catalina.valves.RemoteAddrValve" allow ="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
重启tomcat,输入用户名和密码进行访问。
1 2 3 4 # 停止运行 /opt/tomcat/apache-tomcat-9.0.104/bin/shutdown.sh # 启动 /opt/tomcat/apache-tomcat-9.0.104/bin/startup.sh
Jenkins构建项目 Jenkins中自动构建项目的类型有很多,常用的有以下三种:
自由风格软件项目(FreeStyle Project)
Maven项目(Maven Project)
流水线项目(Pipeline Project)
本文构建项目时使用的war包,源自b站up主,’’涣沷a靑惷’’,原文链接为: https://www.yuque.com/huanfqc/jenkins/jenkins。
war包项目代码地址为:https://share.feijipan.com/s/BWEO9Jad,war包构建具体过程见原文。
Jenkins构建自由风格项目 (1)安装 Deploy to container
插件
(2)新建项目freestyle_demo,配置并拉取gitlab中test_war代码,该过程除包含步骤《部署Jenkins》的过程外,还需进行构建后操作,具体如下图。
(3)配置保存后,,点击Build Now,等待任务构建完成后,访问tomcat,可以看到/websocketChat-1.0-SNAPSHOT
虚拟目录已出现。
Jenkins构建Maven项目 (1)安装Maven Integration
插件
(2)新建项目maven-demo,配置并拉取gitlab中test_war代码,该过程除包含步骤《Jenkins构建自由风格项目》的过程外,还需要在Build时进行修改,具体如下图。
构建时出现报错可将之前配置的阿里云镜像地址改为https
(3)配置保存后,点击Build Now,等待任务构建完成后,访问tomcat,可以看到/websocketChat-1.0-SNAPSHOT
虚拟目录已出现。
Jenkins构建Pipeline流水线项目 Pipeline,简单来说,就是一套运行在Jenkins上的工作流框架,将原来独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作。
如何创建Jenkins Pipeline呢?
在Jenkins的Web Ul中创建Pipeline脚本发布项目 (1)安装Pipeline插件
(2)新建任务Pipeline-demo,使用声明式语法,在Jenkins的Web Ul里创建Pipeline脚本;实现从代码拉取、编译构建、到发布项目。
在Pipeline-demo的配置界面,选择构建触发器-流水线,选择一个脚本模板Hello Word。
点击流水线语法
,在片段生成器中选择checkout:Check out from version control
,按引导填写项目地址和凭证,生成流水线脚本,将拉取代码脚本粘贴到修改后的模板中。
在片段生成器中选择sh:Shell Script
,填写编译命令,生成流水线脚本,将脚本粘贴到修改后的模板中。
在片段生成器中选择deploy:Deploy war/ear to a container
,按引导填写,生成流水线脚本,将脚本粘贴到修改后的模板中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 pipeline { agent any stages { stage('拉取代码' ) { steps { checkout scmGit(branches: [[name: '*/master' ]], extensions: [], userRemoteConfigs: [[credentialsId: 'fbf87557-40b6-468a-91c5-2cfa1b2e33e8' , url: 'http://192.168.1.121:82/test/test_war_demo.git' ]]) } } stage('编译构建' ) { steps { sh 'mvn clean package' } } stage('发布项目' ) { steps { deploy adapters: [tomcat9(credentialsId: '4d9b76aa-078c-462b-81f1-33fe1d9c971c' , path: '' , url: 'http://192.168.1.125:8080/' )], contextPath: null , war: 'target/*.war' } } } }
(3)配置保存后,点击Build Now,等待任务构建完成后,访问tomcat,可以看到/websocketChat-1.0-SNAPSHOT
虚拟目录已出现。
使用Jenkinsfile脚本发布项目 (1)在idea中的项目目录下,选择New-File,创建Jenkinsfile文件,将Pipeline脚本内容粘贴进去,随代码一起发布到项目仓库中。
(2)在任务Pipeline-demo的配置界面,选择构建触发器-流水线,定义内容选择Pipeline script from SCM
-GIt
,填写项目地址和凭证,脚本路径填写Jenkinsfile
。
(3)配置保存后,点击Build Now,等待任务构建完成后,访问tomcat,可以看到/websocketChat-1.0-SNAPSHOT
虚拟目录已出现。
常用构建触发器 Jenkins内置4种构建触发器:
轮询SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。
(1)触发远程构建
在任务Pipeline-demo的配置界面,选择构建触发器
-触发远程构建 (例如,使用脚本)
,自定义身份验证令牌为test
,保存配置。在浏览器中访问:
jenkins地址/job/Pipeline-demo/build?token=TOKEN_NAME
http://192.168.1.124:8888/job/Pipeline-demo/build?token=test ,返回查看任务状态已经开始构建。
(2)其他工程构建后触发(Build after other projects are build)
当需要多个任务先后执行时可用。比如若希望执行freestyle_demo
任务后,再执行Pipeline-demo
,在任务Pipeline-demo的配置界面,选择构建触发器
-Build after other projects are built
,中输入freestyle_demo
,选择只有构建稳定时触发
,保存配置。freestyle_demo任务构建完成后,freestyle_demo开始进行构建。
(3)定时构建(Build periodically)
在任务Pipeline-demo的配置界面,选择构建触发器
-Build periodically
,设置*/1 * * * *
(一分钟一次),保存配置,freestyle_demo任务会每分钟构建一次。
(4)轮询SCM(Poll SCM)
轮询SCM也要设置时间周期,不过与定时构建不同的是,如果在时间周期内代码仓库未发生变化,任务构建就不会进行。比如:在任务Pipeline-demo的配置界面,选择构建触发器
-Poll SCM
,设置*/1 * * * *
(一分钟一次),保存配置。如果在之后的一分钟内代码变更,Pipeline-demo任务会进行构建,反之,直到代码变更后的那一分钟周期内进行构建。
Git hook构建触发器(常用)
当GitLab出现代码变更时,会提交构建请求到Jenkins,Jenkins收到请求后,触发构建。
(1)安装GitLab插件和GitLab Hook插件(新版本自带GitLab Hook插件)
(2)在Jenkins的任务Pipeline-demo的配置界面,选择构建触发器
-Build when a change is pushed to GitLab. GitLab webhook URL: http://192.168.1.124:8888/project/Pipeline-demo
,会出现以下表格中的选项,默认选择即可。
事件类型
触发条件
Push Events
代码推送到分支或标签,包括新分支创建。
Push on Branch Delete
分支被删除时。
Opened Merge Request
创建新的合并请求时触发。
New Commits in MR
向已存在的MR推送新提交时触发(更新MR)。
Accepted (Merged) MR
合并请求被合并到目标分支(如main
)时触发。
Closed MR
合并请求被关闭(未合并)时触发。
(3)在Jenkins中选择Manage Jenkins-System-GitLab中,取消勾选Enable authentication for '/project' end-point
,保存设置。
(4)在GitLab的管理员账户中选择管理中心-设置-网络-外发请求中勾选Allow requests to the local network from web hooks and services
,保存配置。
(5)在GitLab的项目仓库中选择设置-集成,输入webhook URL,选择默认配置,保存。在生成的Webhook右侧,选择Test-Push events,显示Hook executed successfully: HTTP 200
,即为成功。
参数化构建 (1)在源码中创建分支v1,并修改Jenkinsfile脚本中的分支名称,提交代码到gitlab。
修改前: checkout scmGit(branches: [[name: ‘*/master’]]
修改后:checkout scmGit(branches: [[name: ‘*/${branch}’]]
(2)在Jenkins的任务Pipeline-demo的配置界面,选择This project is parameterized
-String Parameter
,具体设置如下图。
(3)保存设置,在任务Pipeline-demo界面选择Build with Parameters
,输入分支的名称,点击Build,进行构建。
配置邮件服务器 (1)安装Email Extension TemplateVersion插件
(2)选择Manage Jenkins-Credentials,点击全局
-Add Credentials
,创建邮件服务器的密码凭证,账户为邮箱地址,密码为获取的邮箱授权码。
(3)选择System
,在Jenkins Location``-系统管理员邮件地址
出输入注册邮箱,在Extended E-mail Notification
处,输入注册邮箱和端口,点击高级
,选择密码凭证,勾选Use SSL
,在Default user e-mail suffix
中邮箱后缀,Default Content Type
选择HTML (text/html)
,Default Recipients
输入注册邮箱,在邮件通知部分输入SMTP服务器和用户默认邮件后缀,点击高级完善信息,勾选通过发送测试邮件测试配置
测试邮件服务器。
(4)构建邮件服务器模板
在项目根目录下创建email.html模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 <!DOCTYPE html > <html > <head > <meta charset ="UTF-8" > <title > ${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title > </head > <body leftmargin ="8" marginwidth ="0" topmargin ="8" marginheight ="4" offset ="0" > <table width ="95%" cellpadding ="0" cellspacing ="0" style ="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif" > <tr > <td > (本邮件是程序自动下发的,请勿回复!)</td > </tr > <tr > <td > <h2 > <font color ="#0000FF" > 构建结果 - ${BUILD_STATUS}</font > </h2 > </td > </tr > <tr > <td > <br /> <b > <font color ="#0B610B" > 构建信息</font > </b > <hr size ="2" width ="100%" align ="center" /> </td > </tr > <tr > <td > <ul > <li > 项目名称 : ${PROJECT_NAME}</li > <li > 构建编号 : 第${BUILD_NUMBER}次构建</li > <li > 触发原因: ${CAUSE}</li > <li > 构建日志: <a href ="${BUILD_URL}console" > ${BUILD_URL}console</a > </li > <li > 构建 Url : <a href ="${BUILD_URL}" > ${BUILD_URL}</a > </li > <li > 工作目录 : <a href ="${PROJECT_URL}ws" > ${PROJECT_URL}ws</a > </li > <li > 项目 Url : <a href ="${PROJECT_URL}" > ${PROJECT_URL}</a > </li > </ul > </td > </tr > <tr > <td > <b > <font color ="#0B610B" > Changes Since Last Successful Build:</font > </b > <hr size ="2" width ="100%" align ="center" /> </td > </tr > <tr > <td > <ul > <li > 历史变更记录 : <a href ="${PROJECT_URL}changes" > ${PROJECT_URL}changes</a > </li > </ul > ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br /> %c<br /> ",showPaths=true,changesFormat="<pre > [%a]<br /> %m</pre > ",pathFormat=" %p"} </td > </tr > <tr > <td > <b > Failed Test Results</b > <hr size ="2" width ="100%" align ="center" /> </td > </tr > <tr > <td > <pre style ="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif" > $FAILED_TESTS</pre > <br /> </td > </tr > <tr > <td > <b > <font color ="#0B610B" > 构建日志 (最后 100行):</font > </b > <hr size ="2" width ="100%" align ="center" /> </td > </tr > <tr > <td > <textarea cols ="80" rows ="30" readonly ="readonly" style ="font-family: Courier New" > ${BUILD_LOG, maxLines=100}</textarea > </td > </tr > </table > </body > </html >
(5)修改Jenkinsfile文件,添加与stages同级的post部分,添加构建后发送邮件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 pipeline { agent any stages { stage('拉取代码' ) { steps { checkout scmGit(branches: [[name: '*/master' ]], extensions: [], userRemoteConfigs: [[credentialsId: 'fbf87557-40b6-468a-91c5-2cfa1b2e33e8' , url: 'http://192.168.1.121:82/test/test_war_demo.git' ]]) } } stage('编译构建' ) { steps { sh 'mvn clean package' } } stage('发布项目' ) { steps { deploy adapters: [tomcat9(credentialsId: '4d9b76aa-078c-462b-81f1-33fe1d9c971c' , path: '' , url: 'http://192.168.1.125:8080/' )], contextPath: null , war: 'target/*.war' } } } post { always { emailext( subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}!' , body: '${FILE,path="email.html"}' , to: '邮箱地址1,邮箱地址2' ) } } }
安装SonarQube Jenkins集成SonarQube进行代码审查。
SonarQube7.9开始不再支持mysql,SonarQube7.8安装支持mysql >=5.6 && <8.0
(1)安装SonarQube前需要安装mysql数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 # 配置mysql5.7的yum源 vi /etc/yum.repos.d/mysql-community.repo [mysql-connectors-community] name=MySQL Connectors Community baseurl=https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-connectors-community-el7-$basearch/ enabled=1 gpgcheck=1 gpgkey=https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 [mysql-tools-community] name=MySQL Tools Community baseurl=https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-tools-community-el7-$basearch/ enabled=1 gpgcheck=1 gpgkey=https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 [mysql-5.7-community] name=MySQL 5.7 Community Server baseurl=https://mirrors.tuna.tsinghua.edu.cn/mysql/yum/mysql-5.7-community-el7-$basearch/ enabled=1 gpgcheck=1 gpgkey=https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 # 安装mysql yum -y install mysql-server # 查看版本 mysql -V systemctl start mysqld systemctl enable mysqld # 查看MySQL的初始密码 grep "password" /var/log/mysqld.log # MySQL的安全性配置 mysql_secure_installation # 按引导配置完后,登录并创建数据库 mysql -uroot -p create database sonar; # 查看数据库 show databases;
(2)安装SonarQube
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 配置系统相关参数 echo "vm.max_map_count=524288 fs.file-max=131072" >> /etc/sysctl.conf sysctl -p # 下载依赖工具 yum install -y unzip wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.8.zip mkdir -p /opt/sonar unzip -q sonarqube-7.8.zip -d /opt/sonar # 创建用户 useradd sonar passwd sonar # 修改sonarqube文件权限 chown -R sonar:sonar /opt/sonar/sonarqube-7.8
(3)修改conf
目录下的sonar.properties
配置文件
1 2 3 sonar.jdbc.username=root sonar.jdbc.password=数据库密码 sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
(4)修改conf
目录下wrapper.conf
的jdk-1.8的路径
1 wrapper.java.command=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.412.b08-1.el7_9.x86_64/bin/java
(5)进入bin/linux-x86-64/
目录,使用sonar用户启动sonarqube
1 2 3 4 su sonar ./sonar.sh start # 查看启动日志 tail ../../logs/sonar.log
使用默认账户登录,账号密码都是admin
(6)登录sonarqube后,选择 Administration
- Security
- Global Permissions
,为admin勾选 Administer System
、 Administer
、 Execute Analysis
、Create
权限。单击右上角头像下拉框,选择 My Account
- Security
,随意填写token名称,完成 Token 的创建。
配置Jenkins与sonarqube集成 (1)在Jenkins上安装SonarQube Scanner
插件,安装完成后,选择Manage Jenkins
-Tools
-SonarQube Scanner 安装
,点击新增SonarQube Scanner
,输入名称,版本选择SonarQube Scanner 4.2.0.1873
,点击保存。
SonarQube 7.8 对应 Sonar-Scanner 4.2
SonarQube 8.9 LTS 对应 Sonar-Scanner 4.6
(2)在Jenkins中配置SonarQube的token凭证。选择类型为Secret text
,输入token,点击创建。
(3)在Jenkins中选择System-SonarQube installations,点击Add SonarQube
,输入SonarQube的地址、选择创建的token凭证,保存集成SonarQube。
非流水线任务添加SonarQube代码审查 在freestyle_demo任务中选择配置-Build Steps,点击增加构建步骤,选择Execute SonarQube Scanner
,选择JDK,输入分析内容,保存配置后,点击Build Now,等待任务构建完成。在SonarQube里查看代码分析结果。
1 2 3 4 5 6 7 8 9 sonar.projectKey=websocketChat sonar.projectName=websocketChat sonar.projectVersion=1.0 sonar.sources=. sonar.java.binaries=./target/classes sonar.exclusions=**/testtarget
流水线任务添加SonarQube代码审查 (1)在项目根目录下,创建sonar-project.properties,写入以下内容。
1 2 3 4 5 6 7 8 9 sonar.projectKey=Pipeline-demo sonar.projectName=Pipeline-demo sonar.projectVersion=1.0 sonar.sources=. sonar.java.binaries=./target/classes sonar.exclusions=**/testtarget
(2)在Jenkinsfile的stages前,引入在Jenkins中安装的SonarQube Scanner作为预置环境变量,之后在拉取代码步骤后,添加审查代码的步骤。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 pipeline { agent any environment { scannerHome = tool 'sonar-scanner-jenkins' } stages { stage('拉取代码' ) { steps { checkout scmGit(branches: [[name: '*/master' ]], extensions: [], userRemoteConfigs: [[credentialsId: 'fbf87557-40b6-468a-91c5-2cfa1b2e33e8' , url: 'http://192.168.1.121:82/test/test_war_demo.git' ]]) } } stage('审查代码' ) { steps { withSonarQubeEnv('SonarQube-jenkins' ) { sh '${scannerHome}/bin/sonar-scanner' } } } stage('编译构建' ) { steps { sh 'mvn clean package' } } stage('发布项目' ) { steps { deploy adapters: [tomcat9(credentialsId: '4d9b76aa-078c-462b-81f1-33fe1d9c971c' , path: '' , url: 'http://192.168.1.125:8080/' )], contextPath: null , war: 'target/*.war' } } } post { always { emailext( subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}!' , body: '${FILE,path="email.html"}' , to: '邮箱地址' ) } } }
(3)代码完成变更后,在流水线任务执行完成,在SonarQube里查看代码分析结果。
应用案例
该应用案例参考来源于b站up主,’’涣沷a靑惷’’,原文链接为: https://www.yuque.com/huanfqc/jenkins/jenkins。
使用Jenkins+GitLab+Docker+SonarQube,在192.168.1.125上部署若依的springboot前后端分离项目。
环境准备 设置Jenkins服务器免密登录192.168.1.125
1 ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.1.125
安装docker 1 2 3 4 5 6 7 8 9 10 11 12 13 bash <(curl -sSL https://linuxmirrors.cn/docker.sh) # 修改镜像源和默认配置文件路径 vi /etc/docker/daemon.json { "data-root": "/data/dockerData", "registry-mirrors": [ "https://docker.1ms.run", "https://docker.xuanyuan.me" ] } # 启动docker systemctl start docker systemctl enable docker
获取并修改源码配置 (1)拉取若依项目源码到本地,并将ruoyi-ui目录与RuoYi-Vue项目放置在同一级
1 git clone https://gitee.com/y_project/RuoYi-Vue.git
(2)修改ruoyi-ui
目录中的vue.config.js
文件,将localhost
修改为部署主机的ip,即192.168.1.125。
1 2 3 4 #修改前 const baseUrl = 'http: #修改后 const baseUrl = 'http:
(3)修改RuoYi-Vue\ruoyi-admin\src\main\resources\application.yml
文件,将redis配置的ip改为192.168.1.125。
1 2 3 4 # redis 配置 redis: # 地址 host: 192.168.1.125
(4)修改RuoYi-Vue\ruoyi-admin\src\main\resources\application-druid.yml
文件,将mysql的链接地址改为192.168.1.125。
1 2 3 4 # 主库数据源 master: url: jdbc:mysql://192.168.1.125:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
(5)在ruoyi-ui目录下,创建sonar-project.properties,写入以下内容,添加SonarQube代码审查
1 2 3 4 5 sonar.projectKey=ruoyi-ui sonar.projectName=ruoyi-ui sonar.projectVersion=1.0 sonar.sources=. sonar.sourceEncoding=UTF-8
(6)在ruoyi-ui目录下创建前端项目的Jenkinsfile文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 pipeline { agent any environment { scannerHome = tool 'sonar-scanner-jenkins' } stages { stage('拉取代码' ) { steps { checkout scmGit(branches: [[name: '*/master' ]], extensions: [], userRemoteConfigs: [[credentialsId: 'fbf87557-40b6-468a-91c5-2cfa1b2e33e8' , url: 'http://192.168.1.121:82/test/ruoyi-ui.git' ]]) } } stage('审查代码' ) { steps { withSonarQubeEnv('SonarQube-jenkins' ) { sh '${scannerHome}/bin/sonar-scanner' } } } stage('打包,部署网站' ) { steps { script { nodejs(nodeJSInstallationName: 'nodejs14' ) { sh ''' npm install # 构建生产环境 npm run build:prod ''' } sh ''' # 将整个 dist 目录复制到挂载目录 scp -r dist 192.168.1.125:/data/ruoyi/nginx/html/ ssh 192.168.1.125 docker restart nginx ''' } } } } }
7)在RuoYi-Vue目录下,创建sonar-project.properties,写入以下内容,添加SonarQube代码审查
1 2 3 4 5 6 7 8 9 sonar.projectKey=ruoyi-api sonar.projectName=ruoyi-api sonar.projectVersion=1.0 sonar.sources=. sonar.java.binaries=./ruoyi-admin/ target/classes sonar.exclusions=**/test/ **,**/target/ ** sonar.java.source=1.8 sonar.java.target=1.8 sonar.sourceEncoding=UTF-8
(8)在RuoYi-Vue目录下创建后端项目的Jenkinsfile文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 pipeline { agent any environment { scannerHome = tool 'sonar-scanner-jenkins' } stages { stage('拉取代码' ) { steps { checkout scmGit(branches: [[name: '*/master' ]], extensions: [], userRemoteConfigs: [[credentialsId: 'fbf87557-40b6-468a-91c5-2cfa1b2e33e8' , url: 'http://192.168.1.121:82/test/ruoyi-api.git' ]]) } } stage('编译构建' ) { steps { sh 'mvn clean package' } } stage('审查代码' ) { steps { withSonarQubeEnv('SonarQube-jenkins' ) { sh '${scannerHome}/bin/sonar-scanner' } } } stage('发布项目' ) { steps { script { sh ''' ssh 192.168.1.125 "mkdir -p /data/ruoyi-api" scp ruoyi-admin/target/*.jar 192.168.1.125:/data/ruoyi-api/ruoyi.jar ''' sh ''' ssh 192.168.1.125 'cat > /data/ruoyi-api/Dockerfile <<-EOF FROM openjdk:8 MAINTAINER xie VOLUME /tmp ADD ruoyi.jar ruoyi.jar ENTRYPOINT ["java","-jar","/ruoyi.jar"] EXPOSE 8080 EOF' ''' sh ''' ssh 192.168.1.125 "docker build -t ruoyi:1.0 /data/ruoyi-api" ''' sh ''' EXISTING_CONTAINER=$(ssh 192.168.1.125 "docker ps -a -q -f name=ruoyi") if [ -n "$EXISTING_CONTAINER" ]; then echo "容器 'ruoyi' 已存在,停止并删除旧容器..." ssh 192.168.1.125 "docker rm -f $EXISTING_CONTAINER" fi ''' sh ''' ssh 192.168.1.125 "docker run -d --name ruoyi -p 8080:8080 ruoyi:1.0" ''' } } } } }
部署项目所需容器 该项目中要用到nginx、mysql和redis,需提前部署好容器。对应容器版本为nginx:1.18.0、mysql:8.0.19、redis:6.0.8
(1)创建所需目录
1 2 3 mkdir -p /data/ruoyi mkdir -p /data/ruoyi/nginx/conf mkdir -p /data/ruoyi/mysql/db
(2)创建nginx临时容器,修改配置文件
1 2 docker run --rm -v /data/ruoyi/nginx/conf:/backup nginx:1.18.0 \ sh -c "cp -r /etc/nginx/. /backup"
修改/data/ruoyi/nginx/conf/conf.d
中的default.conf文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 server { listen 80 ; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header REMOTE-HOST $remote_addr; server_name localhost; location / { root /usr/share/nginx/html/dist; index index.html index.htm; try_files $uri /index.html; } location /prod-api/ { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://192.168.1.125:8080/; } if ($request_uri ~ "/actuator" ) { return 403 ; } }
(3)将RuoYi-Vue\sql
中的sql文件,拷贝到192.168.1.125主机的/data/ruoyi/mysql/db
目录
(4)撰写yml,使用docker compose编排部署容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 vi ruoyi.yml services: nginx: image: nginx:1.18.0 container_name: nginx restart: always volumes: - /data/ruoyi/nginx/conf:/etc/nginx - /data/ruoyi/nginx/logs:/var/log/nginx - /data/ruoyi/nginx/html:/usr/share/nginx/html environment: TZ: "Asia/Shanghai" ports: - "80:80" networks: ruoyi: ipv4_address: 172.20 .112 .11 mysql: container_name: mysql image: mysql:8.0.19 restart: always environment: MYSQL_ROOT_PASSWORD: "password" MYSQL_ALLOW_EMPTY_PASSWORD: "no" MYSQL_DATABASE: "ry-vue" TZ: "Asia/Shanghai" ports: - "3306:3306" volumes: - /data/ruoyi/mysql/db:/var/lib/mysql - /data/ruoyi/mysql/conf:/etc/my.cnf - /data/ruoyi/mysql/init:/docker-entrypoint-initdb.d command: --default-authentication-plugin=mysql_native_password networks: ruoyi: ipv4_address: 172.20 .112 .12 redis: container_name: redis image: redis:6.0.8 restart: always environment: TZ: "Asia/Shanghai" ports: - "6379:6379" volumes: - /data/ruoyi/redis/conf:/etc/redis/redis.conf - /data/ruoyi/redis/data:/data command: redis-server /etc/redis/redis.conf networks: ruoyi: ipv4_address: 172.20 .112 .13 networks: ruoyi: driver: bridge ipam: config: - subnet: 172.20 .112 .0 /24
(5)执行命令创建容器
1 2 3 4 5 6 7 docker compose -f ruoyi.yml up -d # 查看容器运行状态 docker ps # 导入数据库 docker exec -it mysql bash mysql -u root -ppassword ry-vue < /var/lib/mysql/ry_20250417.sql mysql -u root -ppassword ry-vue < /var/lib/mysql/quartz.sql
上传代码到GitLab (1)创建ruoyi-ui和ruoyi-api两个仓库分别存放前端和后端代码
(2)在ruoyi-ui目录下,打开cmd,输入命令上传代码
1 2 3 4 5 6 7 8 9 git init git remote add origin http://192.168.1.121:82/test/ruoyi-ui.git # 添加该目录下的git权限配置 git config user.name "test1" git config user.email "test1@gitlab" # 继续上传 git add . git commit -m "ruoyi-ui" git push -u origin master
(3)在RuoYi-Vue
目录下,打开cmd,输入命令上传代码
1 2 3 4 5 6 7 8 9 git init git remote add origin http://192.168.1.121:82/test/ruoyi-api.git # 添加该目录下的git权限配置 git config user.name "test1" git config user.email "test1@gitlab" # 继续上传 git add . git commit -m "ruoyi-api" git push -u origin master
配置Jenkins流水线 (1)安装nodejs和NodeJS插件
在jenkins服务器上安装nodejs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 wget https://nodejs.org/dist/latest-fermium/node-v14.21.3-linux-x64.tar.gz tar -vxzf node-v14.21.3-linux-x64.tar.gz -C /opt mv /opt/node-v14.21.3-linux-x64 /opt/nodejs # 配置环境变量 echo " export NODE_HOME=/opt/nodejs export PATH=$NODE_HOME/bin:$PATH" >> /etc/profile # 变量生效 source /etc/profile # 查看版版本 node -v npm -v # 配置镜像源 npm config set registry https://registry.npmmirror.com npm config set sass_binary_site=https://npm.taobao.org/mirrors/node-sass
(2)配置NodeJS设置
在Manage Jenkins
-Tools
-NodeJS 安装中,点击新增NodeJS
,填写nodejs的名称为nodejs14
,输入在服务器安装的nodejs路径/opt/nodejs
,保存应用。
(3)创建ruoyi-ui
流水线任务,在流水线-定义中选择Pipeline script from SCM
,SCM选择Git
,填写ruoyi-ui的git仓库地址和登录凭证,其他选项保持默认,保存应用。
(4)点击Build Now
,等待任务执行完成。在浏览器中访问http://192.168.1.125/
,查看前端部署情况。
(5)创建ruoyi-api
流水线任务,在流水线-定义中选择Pipeline script from SCM
,SCM选择Git
,填写ruoyi-api的git仓库地址和登录凭证,其他选项保持默认,保存应用。
(6)点击Build Now
,等待任务执行完成。在浏览器中访问http://192.168.1.125/
,可正常登录,即为成功。
(7)访问sonarQube,分别查看前后端代码的具体质量审查情况。
本篇知识来源于B站视频BV1pF411Y7tq