4、持续集成入门:CI/CD概念、Jenkins安装与配置、Jenkins Pipeline基础、第一个CI任务
好,咱们进入第四章。这一章可以说是整个自动更新体系的「发动机」——持续集成。说白了,就是让代码从提交到部署,中间那堆繁琐的编译、测试、打包工作,全部自动化跑起来。你想想看,如果每次更新都要手动登录服务器敲命令,那跟原始人有什么区别?
4.1 CI/CD 到底是什么?
先别急着装 Jenkins,咱们得先搞清楚 CI/CD 到底在解决什么问题。
CI(持续集成),核心就一句话:频繁地把代码合并到主干,并且每次合并都自动验证。我见过太多团队,开发各自写各自的,一两个月才合并一次,结果合并那天就是灾难日——冲突几百个,编译直接挂掉。嗯,这种痛,经历过的人都懂。
CD(持续交付/持续部署),则是在 CI 的基础上,把验证通过的代码自动部署到目标环境。持续交付是「一键部署」,持续部署是「自动部署」。我个人习惯,生产环境用持续交付,留个人工确认的按钮,心里踏实。
核心价值:
- 尽早发现问题:代码提交后几分钟就知道有没有编译错误、测试失败
- 减少重复劳动:编译、测试、打包这些脏活累活,交给机器干
- 保证交付质量:每次构建都是可追溯、可复现的
4.2 Jenkins 安装与配置
Jenkins 是目前最主流的 CI/CD 工具,没有之一。虽然现在 GitLab CI、GitHub Actions 也很火,但 Jenkins 的灵活性和插件生态,在复杂场景下依然无可替代。
4.2.1 安装方式
我推荐用 Docker 安装,干净利落,不污染宿主机环境。当然,如果你非要直接装到系统里,用 apt 或 yum 也行,但升级维护会麻烦一些。
# 拉取 Jenkins LTS 版本(长期支持版,稳定)
docker pull jenkins/jenkins:lts
# 启动容器,映射端口和持久化目录
docker run -d \
--name jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v /data/jenkins_home:/var/jenkins_home \
jenkins/jenkins:lts
启动后,访问 http://你的服务器IP:8080。第一次登录需要解锁密码,在容器日志里就能找到:
docker logs jenkins 2>&1 | grep "Initial admin password"
注意:我曾经遇到过 Jenkins 容器重启后数据丢失的情况,就是因为忘了挂载 /var/jenkins_home 目录。记住,Jenkins 的所有配置、任务、构建记录都在这个目录里,一定要持久化!
4.2.2 初始配置
解锁后,Jenkins 会引导你安装插件。新手建议选「安装推荐的插件」,里面包含了 Git、Pipeline、Blue Ocean 等常用插件。如果你对网络环境没信心,可以选「选择插件来安装」,只勾选必要的,减少下载时间。
创建管理员用户时,我建议用强密码,因为 Jenkins 一旦暴露在外网,很容易成为攻击目标。嗯,这个坑我也踩过。
4.3 Jenkins Pipeline 基础
Pipeline 是 Jenkins 的核心能力,它把构建过程用代码的方式描述出来。说白了,就是把「点击按钮」变成「写脚本」,好处是版本可控、可复用、可审计。
4.3.1 两种语法
| 语法类型 | 特点 | 适用场景 |
|---|---|---|
| Declarative(声明式) | 结构清晰,容易上手 | 大多数场景,推荐新手使用 |
| Scripted(脚本式) | 灵活强大,可编程 | 复杂逻辑、条件分支多的场景 |
我个人习惯,90% 的场景用声明式就够了。脚本式虽然灵活,但写起来容易失控,维护成本高。
4.3.2 一个最简单的 Pipeline
咱们先写一个 Hello World 级别的 Pipeline,感受一下:
pipeline {
agent any
stages {
stage('拉取代码') {
steps {
echo '正在从 Git 仓库拉取代码...'
// 实际项目中这里会写 git clone 命令
}
}
stage('编译') {
steps {
echo '正在编译项目...'
// 比如 mvn compile 或 npm run build
}
}
stage('测试') {
steps {
echo '正在运行单元测试...'
// 比如 mvn test 或 npm test
}
}
stage('打包') {
steps {
echo '正在打包产物...'
// 比如 mvn package 或 npm run build
}
}
}
post {
success {
echo '恭喜!构建成功!'
}
failure {
echo '构建失败,请检查日志。'
}
}
}
你看,整个流程一目了然:拉代码 → 编译 → 测试 → 打包。每个阶段做什么,失败了怎么办,都写得清清楚楚。
小技巧:在 Jenkins 中新建任务时,选择「流水线(Pipeline)」,然后把上面的代码粘贴到「Pipeline 脚本」框中,保存后点击「立即构建」,就能看到效果了。
4.4 第一个 CI 任务
好,理论讲完了,咱们动手做一个真正的 CI 任务。假设你有一个 Java 项目(用 Maven 管理),每次提交代码后,自动编译、跑测试、打包成 JAR 文件。
4.4.1 准备工作
首先,确保 Jenkins 里安装了以下插件:
- Git Plugin:拉取代码
- Pipeline Plugin:使用 Pipeline 语法
- Maven Integration Plugin:调用 Maven 命令
然后,在 Jenkins 系统配置里,设置 JDK 和 Maven 的路径。如果你用 Docker 安装的 Jenkins,容器里可能没有 JDK 和 Maven,需要手动安装或者使用 Jenkins 的「自动安装」功能。
4.4.2 编写 Pipeline 脚本
pipeline {
agent any
tools {
maven 'Maven-3.8.6' // 这里填你在 Jenkins 里配置的 Maven 名称
jdk 'JDK-11' // 这里填 JDK 名称
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'https://github.com/你的用户名/你的项目.git'
}
}
stage('Build') {
steps {
sh 'mvn clean compile'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Package') {
steps {
sh 'mvn package -DskipTests'
}
}
stage('Archive') {
steps {
archiveArtifacts artifacts: 'target/*.jar'
}
}
}
post {
failure {
emailext(
subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
body: "请查看构建日志: ${env.BUILD_URL}",
to: 'team@example.com'
)
}
}
}
关键点解析:
tools块:指定使用的 Maven 和 JDK 版本,确保环境一致junit命令:收集测试报告,Jenkins 会生成漂亮的测试趋势图archiveArtifacts:把打包好的 JAR 文件保存到 Jenkins 服务器,方便下载emailext:构建失败时自动发邮件通知团队
4.4.3 触发方式
任务建好了,怎么让它自动跑?有两种常用方式:
- 定时触发:比如每天凌晨跑一次,适合对实时性要求不高的项目
- Webhook 触发:代码推送到 Git 仓库时,自动触发构建,这才是真正的「持续集成」
配置 Webhook 很简单:在 Jenkins 任务配置里,勾选「GitHub hook trigger for GITScm polling」,然后在 GitHub 仓库的 Settings → Webhooks 里,添加 Jenkins 的地址(格式:http://你的Jenkins地址/github-webhook/)。
我曾经踩过的坑:Webhook 触发后,Jenkins 一直报 403 错误。查了半天,发现是 Jenkins 的 CSRF 保护没关。如果你遇到类似问题,可以在 Jenkins 系统配置里,找到「全局安全配置」,把「防止跨站点请求伪造」暂时关掉测试一下。当然,生产环境建议用 API Token 的方式解决。
4.5 小结
这一章咱们从 CI/CD 的概念讲起,到 Jenkins 的安装配置,再到 Pipeline 的编写,最后亲手跑通了第一个 CI 任务。你想想看,以前每次提交代码都要手动编译、测试、打包,现在只要 push 一下,Jenkins 全自动搞定,是不是爽多了?
下一章,咱们会深入 Pipeline 的高级用法,比如并行构建、环境变量、参数化构建等。嗯,到时候你会发现自己写的 Pipeline 越来越像「真正的程序」了。