实际开发中,Jenkins的角色可以理解为位于代码库和服务器的“中间”,Jenkins从代码库拉取代码,在主机上调用各种SDK和构建工具构建项目,最终将构建结果发布到服务器上,Jenkins总是需要和其它大量的系统紧密集成并交互,这也是Jenkins中许多功能是插件化实现的原因。总体来说Jenkins配置还是比较复杂的,这篇笔记我们以一个Java工程为例,介绍如何使用Jenkins完成一个全流程的软件构建和发布。
我们这里准备一个SpringBoot2.7工程,它需要使用JDK8和Maven构建。这个Java工程的功能非常简单,它部署后会在8000端口提供服务,当访问/demo/hello
路径时将输出Hello, world!
字符串。我们将这个工程提交到版本控制系统中,例如https://gitee.com/gacfox/demo-jenkins.git
。
虽然Jenkins本身就是使用Java开发的,但Jenkins本身运行所需的Java运行时可能和我们编译所需的JDK版本不同,通常都不可以直接使用。Jenkins和我们本地开发时使用IDE类似,我们可以在Jenkins平台中单独配置JDK和Maven环境,以便使用指定版本的构建工具。对于Java工程,这需要我们安装和配置JDK和Maven。这里要注意的一点是如果我们采用Docker容器部署Jenkins,最好将JDK和Maven的安装路径挂载到容器外面,避免容器重启后安装的内容丢失。此外,为了拉取代码,通常Jenkins主机还需要安装Git命令行工具,不过大多数Linux发行版都自带该命令,因此这里就不展开介绍了。
具体配置Jenkins前,我们需要把JDK和Maven安装到Jenkins主机。这里我们将JDK安装在/opt/java/corretto-jdk-8
路径下,将Maven安装在/opt/apache-maven-3.8.7
路径下。此外,我们还需要确认Jenkins是否已安装Maven插件Maven Integration plugin
(不安装Maven插件也不是不行,我们仍可以通过Shell脚本方式调用Maven,但很不方便)。
接下来我们就可以将JDK和Maven配置到Jenkins了,我们实际上不需要将构建所需的JDK和Maven配置到Jenkins主机的系统环境变量,如果我们不同的工程使用不同版本JDK每次都设置环境变量就太麻烦了,这些环境变量会由Jenkins来设置,我们要做的只是配置Jenkins。在主界面中,点击Manage Jenkins -> Global Tool Configuration
,在这里我们需要指定JDK和Maven的安装路径,我这里的参考配置如下。
JDK Name: openjdk-8
JAVA_HOME: /opt/java/corretto-jdk-8
Maven Name: maven-3.8.7
MAVEN_HOME: /opt/apache-maven-3.8.7
Publish Over SSH
插件除了拉取代码和构建,软件构建完成后我们还需要将构建结果部署到服务器上,我们这里所谓的“服务器”就是一台虚拟机,我们会用到Publish Over SSH
插件,将构建结果传输到服务器并启动服务。实际开发中,我们的部署环境可能是物理机、虚拟机、Docker容器或是Kubernetes等,这通常需要用到不同的插件支持,不过这里我们先不考虑那么复杂,我们先演示最简单的场景,即部署服务器可以通过SSH连接并部署构建结果。
安装完插件后,我们还需要配置服务器的SSH连接信息,点击Manage Jenkins -> Configure System
,在最后可以找到相关配置,我们在Passphrase
字段输入密码,后面的SSH Servers
字段配置服务器的IP、SSH端口等信息即可,我这里的参考配置如下。
Passphrase: SSH私钥密码
Key: 私钥内容
SSH Server Name: 192.168.1.40
Hostname: 192.168.1.40
Username: yuina
此时,我们所需的各种构建环境已配置完成。
配置构建流程也是Jenkins使用中最难的一步,Jenkins经典模式的WebUI用起来其实很不友好,里面有很多坑,新手使用时稍有不慎就会报错,甚至出现明明执行成功但就是没部署成功的尴尬情况,我们这里给出一个成功的配置示例。
首先我们需要在Jenkins主界面点击New Item
按钮新建一个构建配置,在这里我们输入构建配置的名字,构建模式一般选择Freestyle project
。
在Source Code Management
中我们需要配置源代码的Git仓库便于Jenkins拉取代码,这里我们选择Git,并填写如下配置。
Repository URL: https://gitee.com/gacfox/demo-jenkins.git
Credentials: 这里选择配置好的仓库用户名和密码,没有就创建一个
Branches to build: 选择代码分支
在Build
区块中,我们点击Add Build Step
,选择Invoke top-level Maven targets
,添加一个Maven构建配置,配置字段如下。
Maven Version: 这里选择我们之前配置的Maven信息
Goals: clean package
构建完成后,我们还需要将构建结果通过SSH传输到目标服务器上并启动,这需要在Post-build Actions
中点击Add post-build action
,选择Send build artifacts over SSH
,配置如下。
SSH Server Name: 这里选择我们之前配置好的SSH地址
Transfer Set Sources files: **/demo-jenkins-0.0.1-SNAPSHOT.jar
Remove prefix: target
Exec command: pkill java ; nohup java -jar /home/yuina/demo-jenkins-0.0.1-SNAPSHOT.jar > app.log 2>&1 &
配置中,Transfer Set Sources files
设置的是要通过SSH传输到主机的文件,我们这里由于是SpringBoot工程,因此传输的内容就是一个JAR文件,Remove prefix
用于配置“前缀文件夹移除”,这是因为我们构建后的结果实际上位于工程目录的target/demo-jenkins-0.0.1-SNAPSHOT.jar
,我们配置这个前缀移除后就可以将文件拷贝到目标主机的~/demo-jenkins-0.0.1-SNAPSHOT.jar
而不是~/target/demo-jenkins-0.0.1-SNAPSHOT.jar
,这块可能Jenkins设计的就比较混乱,我们如果暂时不能理解可以自己动手实验。
最后是启动命令,它也会通过SSH在目标主机执行执行,我们的启动命令很简单,首先pkill
结束原来的Java进程,无论pkill
是否成功,都重新启动我们的程序。这是一种比较简单暴力的写法,对于像这样的简单程序倒也还算可用,但如果我们的程序启停流程比较复杂,最好还是采用编写单独的Shell脚本等方式来实现更新和重启。
注意:这里我们没有配置目标主机的传输路径,文件默认会传输到SSH登录后的当前目录,一般为用户的家目录。
当构建配置好后,执行它就非常简单了,我们点击绿色的三角按钮即可,如果构建执行成功,我们会看到构建状态是一个小太阳图标,如果构建失败这里则会显示下雨图标,意味着我们的代码编译没有通过,或是构建配置、目标主机等存在问题。
如果你的构建流程无法跑通,这个问题定位起来就比较复杂了,你需要仔细查看日志,是拉取代码时出错了,还是构建过程出错了,又或者是部署主机的问题?总而言之,这里无法明确给出一个答案,这种问题需要你有丰富的软件工程经验来解决,因此如果你是一个纯新手,自己折腾Jenkins可以有相当的难度。