使用Maven构建Java应用程序
你将在Github示例仓库中获取一个输出"Hello world!"字符串的简单Java应用,该应用还包含若干单元测试,用于检查main方法。 测试结果保存在JUnit XML报告中。请确保你本地安装了Git。
在 Docker中运行Jenkins
在本教程中, 将Jenkins作为 Docker 容器并从 jenkinsci/blueocean
Docker 镜像中运行。
在 Linux 系统上
打开终端窗口
-
使用下面的
docker run
命令运行jenkinsci/blueocean
镜像作为Docker中的一个容器(记住,如果本地没有镜像,这个命令会自动下载):docker run \ --rm \ -u root \ -p 8080:8080 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$HOME":/home \ jenkinsci/blueocean
| | 将容器中的
/var/jenkins_home
目录映射到 Docker volume ,并将其命名为jenkins-data
。如果该卷不存在, 那么docker run
命令会自动为你创建卷。 |
| | 将主机上的$HOME
目录 (即你的本地)映射到 (通常是/Users/
目录) 到容器的/home
目录。 |Note: 如果复制或粘贴上面的命令片段不起作用, 尝试复制和粘贴这个没有注释的版本:
docker run \ --rm \ -u root \ -p 8080:8080 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "$HOME":/home \ jenkinsci/blueocean
访问 Jenkins/Blue Ocean Docker 容器
如果你有一些使用 Docker 的经验,希望或需要使用 docker exec
命令通过一个终端/命令提示符来访问 Jenkins/Blue Ocean Docker 容器, 你可以添加如 --name jenkins-tutorials
选项(与上面的 docker run
), 这将会给Jenkins/Blue Ocean Docker容器一个名字 "jenkins-tutorials"。
这意味着你可以通过 docker exec
命令访问Jenkins/Blue Ocean 容器(通过一个单独的终端 /命令提示窗口) ,例如:
docker exec -it jenkins-tutorials bash
安装向导
在你访问 Jenkins之前, 你需要执行一些快速的 "一次性" 步骤。
解锁 Jenkins
当你第一次访问一个新的 Jenkins 实例时, 要求你使用自动生成的密码对其进行解锁。
-
当在终端/命令提示窗口出现两组星号时, 浏览
http://localhost:8080
并等待 Unlock Jenkins 页面出现。 - 再次从终端/命令提示窗口, 复制自动生成的字母数字密码(在两组星号之间)。
在 Unlock Jenkins 页面, 粘贴该密码到 Administrator password 字段并点击 Continue。
使用插件自定义 Jenkins
在 解锁 Jenkins后, Customize Jenkins 页面出现。
在该页面,点击 Install suggested plugins。
安装向导显示了正在配置的Jenkins的进程,以及建议安装的插件。这个过程肯需要几分钟。
创建第一个管理员用户
最后, Jenkins 要求创建你的第一个管理员用户。
当 Create First Admin User 页面出现, 在相应的字段中指定你的详细消息并点击 Save and Finish。
-
当 Jenkins is ready 页面出现, 点击 Start using Jenkins。
Notes:该页面可能表明 Jenkins is almost ready! 如果相反, 点击 Restart.
如果该页面在一分钟后没有自动刷新, 使用你的web浏览器手动刷新。
如果需要,登录 Jenkins , 你就可以开始使用 Jenkins了!
停止和重启 Jenkins
在本教程的其余部分, 你可以通过在终端/命令提示窗口输入 Ctrl-C
停止 Jenkins/Blue Ocean Docker 容器,你可以从中运行<docker run ...
命令。
要重启Jenkins/Blue Ocean Docker 容器:
在上面的 Linux上运行相同的
docker run ...
命令 。
Note: 如果有更新的话,该进程会更新jenkinsci/blueocean
Docker 镜像。浏览
http://localhost:8080
。等待直到登录页面出现并登陆。
clone GitHub示例仓库
通过将应用程序源代码所在的示例仓库fork到你自己的Github账号中, 并clone到本地,你就可以获取一个"Hello world!"简单Java应用程序。
示例仓库 simple-java-maven-app
放到你的Git仓库中。
在Jenkins中创建你的流水线项目
回到Jenkins,如果有必要的话重新登录,点击 Welcome to Jenkins! 下方的 create new jobs
注意: 如果你无法看见以上内容,点击左上方的 New Item 。在 Enter an item name 域中,为新的流水线项目指定名称(例如
simple-java-maven-app
)。向下滚动并单击 Pipeline,然后单击页面末尾的 OK 。
( 可选 ) 在下一页中,在 Description 字段中填写流水线的简要描述 (例如
一个演示如何使用Jenkins构建Maven管理的简单Java应用程序的入门级流水线。
)点击页面顶部的 Pipeline 选项卡,向下滚动到 Pipeline 部分。
在 Definition 域中,选择 Pipeline script from SCM 选项。此选项指示Jenkins从源代码管理(SCM)仓库获取你的流水线, 这里的仓库就是你clone到本地的Git仓库。
在 SCM 域中,选择 Git。
-
在 Repository URL 域中,填写你本地仓库的 目录路径, 这是从你主机上的用户账户home目录映射到Jenkins容器的
/home
目录:- Linux系统 -
/home/GitHub/simple-java-maven-app
- Linux系统 -
-
点击 Save 保存你的流水线项目。你现在可以开始创建你的
Jenkinsfile
,这些文件会被添加到你的本地仓库。
将你的初始流水线创建为Jenkinsfile
现在你已准备好创建你的流水线,它将使用Jenkins中的Maven自动构建你的Java应用程序。 你的流水线将被创建为 Jenkinsfile
,它将被提交到你本地的Git仓库(simple-java-maven-app
)。
这是 "Pipeline-as-Code" 的基础,它将持续交付流水线作为应用程序的一部分,与其他代码一样进行版本控制和审查。 阅读更多关于 流水线 的信息,以及用户手册中的 使用Jenkinsfile 章节。
首先,创建一个初始流水线来下载Maven Docker镜像,并将其作为Docker容器运行(这将构建你的简单Java应用)。 同时添加一个“构建”阶段到流水线中,用于协调整个过程。
使用你最称手的文本编辑器或者IDE,在你本地的
simple-java-maven-app
Git仓库的根目录创建并保存一个名为Jenkinsfile
的文本文件。-
复制以下声明式流水线代码并粘贴到
Jenkinsfile
文件中:pipeline { agent { docker { image 'maven:3-alpine' args '-v /root/.m2:/root/.m2' } } stages { stage('Build') { steps { sh 'mvn -B -DskipTests clean package' } } } }
| | 这里的
image
参数(参考agent
章节的docker
参数) 是用来下载maven:3-apline
Docker镜像 (如果你的机器还没下载过它)并将该镜像作为单独的容器运行。这意味着:你将在Docker中本地运行相互独立的Jenkins和Maven容器。
Maven容器成为了Jenkins用来运行你的流水线项目的 agent。 这个容器寿命很短——它的寿命只是你的流水线的执行时间。
|
| | 这里的args
参数在暂时部署的Maven Docker容器的/root/.m2
(即Maven仓库)目录 和Docker主机文件系统的对应目录之间创建了一个相互映射。这背后的实现细节超出了本教程的范围,在此不做解释。 但是,这样做的主要原因是,在Maven容器的生命周期结束后,构建Java应用程序所需的工件 (Maven在流水线执行时进行下载)能够保留在Maven存储库中。这避免了在后续的流水线执行过程中, Maven反复下载相同的工件。请注意,不同于你为jenkins-data
创建的Docker数据卷,Docker主机的文件系统在每次重启Docker时都会被清除。 这意味着每次Docker重新启动时,都会丢失下载的Maven仓库工件。 |
| | 定义了一个名为Build
的stage
,之后会出现在Jenkins UI上。 |
| | 这里的sh
step(参考steps
章节)运行Maven命令干净地构建你的Java应用(不运行任何tests)。 | 保存对
Jenkinsfile
的修改并且将其提交到你本地的simple-java-maven-app
Git仓库。例如,在simple-java-maven-app
目录下,运行以下命令:
git add .
继续运行
git commit -m "Add initial Jenkinsfile"
再次回到Jenkins,如果有必要的话重新登录,点击左侧的 Open Blue Ocean 进入Jenkins的Blue Ocean界面。
-
在 This job has not been run 消息框中,点击 Run,然后快速点击右下角出现的 OPEN 链接, 观察Jenkins运行你的流水线项目。如果你不能点击 OPEN 链接,点击Blue Ocean主界面的一行来使用这一特性。
注意: 你可能需要几分钟时间等待第一次运行完成。在clone了你的本地simple-java-maven-app
Git仓库后, Jenkins接下来做了以下动作:将项目排入队列等待在agent上运行。
-
下载Maven Docker镜像,并且将其运行在Docker中的一个容器中。
[图片上传中...(image-d4aad8-1574158061583-1)]
-
在Maven容器中运行
Build
阶段 (Jenkinsfile
中所定义的)。在这期间,Maven会下载构建你的Java应用所需的工件, 这些工件最终会被保存在Jenkins的本地Maven仓库中(Docker的主机文件系统)。
若Jenkins成功构建了你的Java应用,Blue Ocean界面会变为绿色。
-
点击右上方的 X 回到Blue Ocean主界面。
为你的流水线增加test阶段
回到你的文本编辑器/IDE,打开你的
Jenkinsfile
。-
复制以下声明式流水线代码,并粘贴到
Jenkinsfile
中Build
阶段的下方:stage('Test') { steps { sh 'mvn test' } post { always { junit 'target/surefire-reports/*.xml' } } }
最终的代码为:
pipeline { agent { docker { image 'maven:3-alpine' args '-v /root/.m2:/root/.m2' } } stages { stage('Build') { steps { sh 'mvn -B -DskipTests clean package' } } stage('Test') { steps { sh 'mvn test' } post { always { junit 'target/surefire-reports/*.xml' } } } } }
| | 定义了一个名为
Test
的stage
,之后会出现在Jenkins UI上。 |
| | 这里的sh
step (参考steps
章节)执行Maven命令来运行你的Java应用的单元测试。 这个命令还生成一个JUnit XML报告,保存在target/surefire-reports
目录 (位于Jenkins容器中的/var/jenkins_home/workspace/simple-java-maven-app
目录)。 |
| | 这里的junit
step (由 JUnit Plugin 提供)用于归档JUnit XML报告(由上面的mvn test
命令生成) 并通过Jenkins接口公开结果。在Blue Ocean中,可以在流水线运行的 Tests 页面获取结果。post
章节的always
条件包含了这个junit
step, 保证了这个step 总是 在Test
阶段 结束后 执行,不论该阶段的运行结果如何。 | 保存对
Jenkinsfile
的修改并将其提交到你的本地simple-java-maven-app
Git仓库。例如,在simple-java-maven-app
目录下,运行以下命令:
git stage .
继续运行
git commit -m "Add 'Test' stage"
再次回到Jenkins,如果有必要的话重新登录,进入Jenkins的Blue Ocean界面。
-
点击左上方的 Run 然后快速点击右下方出现的 OPEN 链接, 观察Jenkins运行你修改过的流水线项目。 如果你不能点击 OPEN 链接,点击Blue Ocean主界面的 top 行来使用这一特性。
注意: 你会发现本次运行Jenkins不再需要下载Maven Docker镜像。Jenkins只需要从之前下载的Maven镜像运行 一个新的容器。另外,如果最近一次运行 流水线 后,Docker没有重启, 那么在 "Build" 阶段无需下载Maven工件。因此,你的流水线再次运行时速度会更快。
如果你修改过的流水线运行成功,Blue Ocean界面看起来会像下面这样。注意增加的 "Test" 阶段。 你可以点击之前的 "Build" 阶段来获取阶段输出结果。 点击右上方的 X 回到Blue Ocean主界面。
为你的流水线增加deliver阶段
回到你的文本编辑器/IDE,打开你的
Jenkinsfile
。-
复制以下声明式流水线代码,并粘贴到
Jenkinsfile
中Test
阶段的下方:stage('Deliver') { steps { sh './jenkins/scripts/deliver.sh' } }
最终的代码为:
pipeline { agent { docker { image 'maven:3-alpine' args '-v /root/.m2:/root/.m2' } } stages { stage('Build') { steps { sh 'mvn -B -DskipTests clean package' } } stage('Test') { steps { sh 'mvn test' } post { always { junit 'target/surefire-reports/*.xml' } } } stage('Deliver') { steps { sh './jenkins/scripts/deliver.sh' } } } }
| | 定义了一个名为
Deliver
的stage,之后会出现在Jenkins UI上。 |
| | 这里的sh
step (参考steps
章节)执行位于jenkins/scripts
目录下的shell脚本deliver.sh
, 该目录位于simple-java-maven-app
仓库根目录下。deliver.sh
文件所做动作包含在其自身文本内容中。 一般的原则是,尽量保持你的流水线代码(即Jenkinsfile
)越简洁越好,将更复杂的构建步骤放在多个独立的shell脚本中 (尤其对于那些包含2个以上steps的stage)。这最终会使得维护你的流水线代码变得更容易,特别是当你的流水线变得越来越复杂的时候。 | 保存对
Jenkinsfile
的修改并将其提交到你的本地simple-java-maven-app
Git仓库。例如,在simple-java-maven-app
目录下,运行以下命令:
git stage .
继续运行
git commit -m "Add 'Deliver' stage"
再次回到Jenkins,如果有必要的话重新登录,进入Jenkins的Blue Ocean界面。
-
点击左上方的 Run 然后快速点击右下方出现的 OPEN 链接, 观察Jenkins运行你修改过的流水线项目。 如果你不能点击 OPEN 链接,点击Blue Ocean主界面的 top 行来使用这一特性。
如果你修改过的流水线运行成功,Blue Ocean界面看起来会像下面这样。注意增加的 "Deliver" 阶段。 你可以点击之前的 "Test" 和 "Build" 阶段来获取阶段输出结果。以下是 "Deliver" 阶段的输出应该是什么样子,向你展示最终Java应用程序的执行结果。
-
点击右上方的 X 回到Blue Ocean主界面,列表显示流水线历史运行记录,按时间顺序倒序排列。