Jenkins
用户手册:Jenkins 用户手册
Jenkins 是什么
Jenkins 是常见的 CI/CD 工具,用来自动完成代码拉取、编译、测试、打包、构建镜像和部署。它的价值不是“点按钮部署”,而是把发布流程标准化、可追踪、可回滚。
零基础可以把 Jenkins 理解成一个“自动执行发布步骤的调度系统”:
- 你把固定步骤写成脚本或 Jenkinsfile。
- Jenkins 在指定时机触发这些步骤。
- 每次执行都会留下日志、状态、产物和责任记录。
- 失败时可以知道失败在哪一步,而不是靠人工回忆。
如果没有 Jenkins,项目发布通常会变成“谁会发谁来发”。这种方式在小项目里看起来快,但项目一多就会出现几个问题:步骤容易漏、环境容易不一致、失败原因不好追踪、生产发布不可审计、新人不敢接手。
典型流水线
flowchart TD
A["1. 触发构建<br/>Webhook / 定时 / 手动"] --> B["2. 构建检查<br/>拉代码 / 编译 / 测试"]
B --> C{"质量是否通过"}
C -->|否| X["失败通知<br/>停止发布"]
C -->|是| D["3. 交付产物<br/>Jar / dist / Docker 镜像"]
D --> E["4. 部署验证<br/>发布 / 健康检查 / 回滚"]
E --> F["5. 记录结果<br/>版本 / 日志 / 通知"]这张图要重点理解三个边界:
| 边界 | 说明 | 如果忽略会怎样 |
|---|---|---|
| 构建边界 | 拉代码、编译、测试、打包都发生在 Jenkins 构建环境 | 本地能跑不代表 Jenkins 能跑,依赖、JDK、Node 版本可能不同 |
| 交付边界 | 构建完成后产生 Jar、dist、Docker 镜像等产物 | 没有固定产物就无法追踪“线上到底跑的是哪一版” |
| 部署边界 | Jenkins 只负责执行部署动作,服务是否真正可用要靠健康检查验证 | 命令执行成功但应用启动失败,会造成“显示成功,线上不可用” |
Jenkins 的核心工作原理
flowchart TD
Controller["Jenkins Controller"]
Queue["构建队列"]
Agent1["Agent 节点 A"]
Agent2["Agent 节点 B"]
Workspace["工作目录 Workspace"]
Log["构建日志"]
Artifact["构建产物"]
Controller --> Queue
Queue --> Agent1
Queue --> Agent2
Agent1 --> Workspace
Agent2 --> Workspace
Workspace --> Log
Workspace --> ArtifactJenkins 不是简单地“在网页上执行命令”。它内部至少有几个角色:
| 角色 | 做什么 | 初学者容易误解的点 |
|---|---|---|
| Controller | 保存任务配置、调度构建、管理插件和凭据 | 不建议把所有重任务都压在 Controller 上执行 |
| Agent | 真正运行构建命令的机器或容器 | Agent 上必须有 JDK、Maven、Docker、Node 等工具 |
| Job | 一个构建任务,可以是 Freestyle 或 Pipeline | Job 是配置入口,不等于一次构建 |
| Build | Job 的一次执行记录 | 每次 Build 都应该能追踪代码版本、日志和产物 |
| Workspace | 构建时检出的代码目录 | Workspace 不是长期存储,不要把关键文件只放这里 |
| Credential | Jenkins 管理的密码、Token、私钥 | 密钥不要写进 Jenkinsfile 或 shell 脚本 |
Jenkins 的执行过程可以拆成一句话:
Controller 接到触发信号后,把任务放进队列,再分配给合适的 Agent;Agent 在 Workspace 中按 Jenkinsfile 执行命令,并把日志、状态、产物回传给 Jenkins。
Freestyle 和 Pipeline
| 类型 | 特点 | 适合场景 |
|---|---|---|
| Freestyle | 页面配置,容易上手 | 简单任务、临时任务 |
| Pipeline | 使用 Jenkinsfile 作为代码管理 | 正式项目、多阶段流水线 |
正式项目更推荐 Pipeline,因为发布流程可以和代码一起版本化,变更有记录,也方便复制到其他项目。
为什么 Pipeline 更适合正式项目:
| 对比点 | Freestyle | Pipeline |
|---|---|---|
| 配置位置 | Jenkins 页面里点出来 | 仓库中的 Jenkinsfile |
| 版本管理 | 不容易追踪谁改过 | 和代码一起走 Git |
| 复用能力 | 多项目复制困难 | 可以提取 Shared Library |
| 复杂流程 | 分支、并行、人工确认较麻烦 | 适合多阶段、多环境、多分支 |
| 审计能力 | 要依赖 Jenkins 配置历史 | 代码评审就能看到流程变更 |
Jenkinsfile 简单示例
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Docker Build') {
steps {
sh 'docker build -t lautrans-api:${BUILD_NUMBER} .'
}
}
}
}这个 Demo 的执行含义:
agent any表示 Jenkins 可以找任意可用节点执行。Checkout阶段拉取当前仓库代码。Build阶段执行 Maven 编译和测试。Docker Build阶段把应用打成镜像。
如果是正式发布,还应该继续补上镜像推送、部署和健康检查:
pipeline {
agent any
environment {
IMAGE = "registry.example.com/lautrans-api:${BUILD_NUMBER}"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('Package') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Build Image') {
steps {
sh 'docker build -t $IMAGE .'
}
}
stage('Push Image') {
steps {
withCredentials([usernamePassword(
credentialsId: 'docker-registry',
usernameVariable: 'DOCKER_USER',
passwordVariable: 'DOCKER_PASSWORD'
)]) {
sh 'echo "$DOCKER_PASSWORD" | docker login registry.example.com -u "$DOCKER_USER" --password-stdin'
sh 'docker push $IMAGE'
}
}
}
stage('Deploy') {
steps {
sh 'kubectl set image deployment/lautrans-api lautrans-api=$IMAGE -n prod'
}
}
stage('Health Check') {
steps {
sh 'kubectl rollout status deployment/lautrans-api -n prod --timeout=120s'
}
}
}
post {
success {
echo "发布成功:${IMAGE}"
}
failure {
echo "发布失败,请查看失败阶段日志"
}
}
}这份 Jenkinsfile 不是为了让你直接复制到生产,而是为了理解正式流水线应该具备哪些环节:测试要先于打包,镜像要有唯一版本,密钥要走 Jenkins 凭据,部署后要做健康检查。
每个阶段为什么存在
| 阶段 | 解决什么问题 | 如果不做会怎样 |
|---|---|---|
| Checkout | 明确本次构建使用哪份代码 | 线上版本无法和 Git 提交对应 |
| Test | 在发布前发现基础错误 | Bug 进入后续阶段,回滚成本变高 |
| Package | 生成可交付产物 | 部署机器还要重新编译,环境不一致 |
| Build Image | 固化运行环境和应用文件 | 不同机器 JDK、依赖、系统库差异会影响结果 |
| Push Image | 把产物交给统一仓库管理 | 多台机器无法稳定拉到同一份产物 |
| Deploy | 把新版本应用到目标环境 | 只能人工登录服务器执行命令 |
| Health Check | 验证服务真正启动成功 | 命令成功但业务不可用,问题发现太晚 |
| Notification | 通知相关人员处理成功或失败 | 失败无人知道,问题拖到用户反馈 |
最小可运行 Demo
假设你有一个 Spring Boot 项目,项目根目录有 pom.xml 和 Dockerfile。
Dockerfile 示例:
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]本地先验证这些命令能跑:
mvn clean package
docker build -t lautrans-api:local .
docker run --rm -p 8080:8080 lautrans-api:local再放到 Jenkinsfile:
pipeline {
agent any
stages {
stage('Package') {
steps {
sh 'mvn clean package'
}
}
stage('Image') {
steps {
sh 'docker build -t lautrans-api:${BUILD_NUMBER} .'
}
}
}
}学习 Jenkins 时不要一开始就上生产部署。先让 Jenkins 能稳定完成“拉代码、测试、打包、构建镜像”四步,再增加推送镜像和部署。
发布时要注意什么
- 密码、Token、服务器私钥要放在 Jenkins 凭据中,不要写进 Jenkinsfile。
- 构建产物和镜像 tag 要可追踪,建议包含构建号或 Git 提交号。
- 部署后要做健康检查,不能只看命令执行成功。
- 失败时要有通知和回滚方案。
- 生产发布最好加入人工确认节点,避免误发。
常见问题排查
| 问题 | 排查方向 |
|---|---|
| 拉代码失败 | 检查 Git 凭据、仓库地址、分支权限 |
| Maven 构建慢 | 检查本地仓库缓存、镜像源、依赖下载 |
| Docker 命令失败 | 检查 Jenkins 用户是否有 Docker 权限 |
| 部署后服务不可用 | 检查日志、端口、环境变量、数据库连接 |
| 流水线卡住 | 检查是否等待人工输入或节点资源不足 |
学习路线
这篇只负责建立整体认知。继续学习时建议按下面顺序走:
- 入门路线:从安装、任务创建、凭据、构建记录开始。
- Pipeline:深入理解 Jenkinsfile、阶段、环境变量、参数、并行和人工确认。
- Shared Library:学习多项目如何复用流水线逻辑。
- 项目实战:把 Spring Boot、Docker、镜像仓库和部署流程串起来。
