1688 字
8 分钟
Jenkins 入门:从构建任务到 CI/CD 流水线

Jenkins 是一个常见的自动化构建与持续集成工具。它通常用于自动完成代码拉取、编译、测试、打包、镜像构建和部署等流程。

如果没有 Jenkins,一个项目发布可能需要人工重复执行:

登录服务器

拉取最新代码

执行编译和测试

打包部署产物

停止旧服务

启动新服务

这些步骤不难,但重复、繁琐,并且容易因为人工操作产生问题。Jenkins 的价值,就是把这类流程变成一条稳定、可重复、可追踪的自动化流水线。

CI/CD 与 Jenkins 的位置#

学习 Jenkins 之前,先理解 CI/CD:

CI = Continuous Integration
持续集成

CD = Continuous Delivery / Continuous Deployment
持续交付 / 持续部署

CI 关注的是:代码提交后,能不能尽快完成集成、构建和测试。

CD 关注的是:代码通过验证后,能不能稳定地交付或部署到目标环境。

一个典型流程可以理解成:

Developer

    │ git push

GitHub / GitLab / Gitee

    │ Webhook

Jenkins

    ├── Checkout
    ├── Build
    ├── Test
    ├── Package
    ├── Docker Build
    └── Deploy


Test / Production

所以 Jenkins 不只是一个“点击构建”的工具,它更像是一个流程编排平台:把 Git、Maven、JUnit、Docker、Shell、服务器部署等动作串起来。

Jenkins 的几个核心概念#

Jenkins 里最常见的几个概念是:

概念说明
JobJenkins 中的一项自动化任务
BuildJob 每执行一次产生的一次构建记录
WorkspaceJenkins 拉取代码、执行命令的工作目录
Plugin插件,提供 Git、Pipeline、Docker、凭据等能力
Node / Agent真正执行构建任务的节点
Pipeline用代码描述 CI/CD 流程,通常写在 Jenkinsfile

例如一个 Java 项目的 Workspace 可能是:

/var/lib/jenkins/workspace/demo-backend/

里面通常会有:

demo-backend
├── Jenkinsfile
├── Dockerfile
├── pom.xml
├── deploy.sh
└── src

Jenkins 在这个目录中执行:

mvn clean package

但需要注意:Jenkins 本身不会编译 Java,真正编译 Java 的是 Maven 或 Gradle。
Jenkins 做的是调度这些工具,并记录每一步的执行结果。

安装与第一个任务#

Jenkins 有多种安装方式,例如 Linux 软件包、Docker、War 包或 Kubernetes。个人学习时,用 Docker 启动会比较方便:

docker run \
  -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

启动后访问:

http://服务器IP:8080

第一次进入 Jenkins 时,需要获取初始管理员密码:

docker exec jenkins \
cat /var/jenkins_home/secrets/initialAdminPassword

进入页面后,可以创建一个最简单的 Freestyle Job:

新建任务

Freestyle project

配置 Git 仓库

添加 Execute shell

mvn clean package

这个任务的本质就是:

Jenkins

Git Clone

Maven Build

生成 Jar

不过当流程变复杂后,页面配置会越来越难维护,所以真实项目更推荐使用 Pipeline。

Jenkinsfile 与 Pipeline#

Pipeline 是 Jenkins 中更推荐的使用方式。它把构建流程写成代码,通常保存在项目根目录的 Jenkinsfile 中。

最小的 Jenkinsfile 可以这样写:

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo '开始构建'
            }
        }
    }
}

它的结构可以理解为:

Pipeline

Stages

Stage

Steps

一个更接近 Java 项目的 Pipeline 示例:

pipeline {
    agent any

    environment {
        APP_NAME = 'demo'
        IMAGE_NAME = 'demo'
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        stage('Test') {
            steps {
                sh 'mvn clean test'
            }
        }

        stage('Package') {
            steps {
                sh 'mvn clean package -DskipTests'
            }
        }

        stage('Docker Build') {
            steps {
                sh '''
                    docker build \
                      -t demo:${BUILD_NUMBER} .
                '''
            }
        }

        stage('Deploy') {
            steps {
                sh './deploy.sh'
            }
        }
    }

    post {
        success {
            echo 'Pipeline 执行成功'
        }

        failure {
            echo 'Pipeline 执行失败'
        }
    }
}

其中:

  • agent any 表示使用任意可用节点执行流水线。
  • stage 表示流水线中的一个阶段,例如测试、打包、部署。
  • steps 表示这个阶段中真正执行的命令。
  • environment 用来定义环境变量。
  • post 用来处理构建结束后的动作,例如成功通知、失败通知或清理资源。

参数、凭据与自动触发#

实际项目经常需要区分不同部署环境,例如 devtestprod。可以通过 parameters 做参数化构建:

pipeline {
    agent any

    parameters {
        choice(
            name: 'ENV',
            choices: ['dev', 'test', 'prod'],
            description: '请选择部署环境'
        )
    }

    stages {
        stage('Deploy') {
            steps {
                echo "当前部署环境:${params.ENV}"
                sh "./deploy.sh ${params.ENV}"
            }
        }
    }
}

如果涉及账号、Token、SSH Key、Docker Registry 密码,不要直接写在 Jenkinsfile 里:

PASSWORD = '123456'

更推荐使用 Jenkins 的 Credentials 统一管理,然后在 Pipeline 中引用:

withCredentials([
    usernamePassword(
        credentialsId: 'docker-registry-password',
        usernameVariable: 'USERNAME',
        passwordVariable: 'PASSWORD'
    )
]) {
    sh '''
        docker login \
          -u $USERNAME \
          -p $PASSWORD
    '''
}

如果希望代码提交后自动构建,可以使用 Webhook:

Developer
  ↓ git push
GitLab / GitHub
  ↓ Webhook
Jenkins

Pipeline

这样每次代码 Push 后,Git 平台会主动通知 Jenkins,Jenkins 再自动启动构建流程。

Docker 部署示例#

现在很多 Java 项目会先构建 Jar,再构建 Docker 镜像。

一个简单的 Dockerfile

FROM eclipse-temurin:17-jre

COPY target/demo.jar /app/demo.jar

ENTRYPOINT ["java", "-jar", "/app/demo.jar"]

Jenkinsfile 中可以增加镜像构建阶段:

stage('Docker Build') {
    steps {
        sh '''
            docker build \
              -t registry.example.com/demo:${BUILD_NUMBER} .
        '''
    }
}

再增加镜像推送阶段:

stage('Docker Push') {
    steps {
        sh '''
            docker push \
              registry.example.com/demo:${BUILD_NUMBER}
        '''
    }
}

部署时可以让服务器拉取指定镜像并重启容器:

docker stop demo || true
docker rm demo || true

docker run \
  -d \
  --name demo \
  -p 8080:8080 \
  registry.example.com/demo:${BUILD_NUMBER}

这样从代码提交到服务部署,就形成了一条比较完整的 CI/CD 链路。

常见问题与实践建议#

Jenkins 构建失败时,第一反应不应该是“Jenkins 坏了”,而是先看 Console Output,确认具体失败在哪个 Stage、哪条命令。

常见问题一般来自这些地方:

  • java: command not found:Jenkins 进程没有正确配置 Java 或 JAVA_HOME
  • mvn: command not found:Jenkins 用户找不到 Maven。
  • Permission denied:脚本没有执行权限,或 Jenkins 用户没有目录权限。
  • Docker 权限错误:Jenkins 用户无法访问 Docker daemon。
  • Git Clone 失败:仓库地址、Token、SSH Key 或网络配置有问题。
  • Workspace 文件残留:上一次构建产物影响本次构建,可以使用 mvn cleancleanWs() 清理。

实践中建议遵循几个原则:

  • 不要把密码、Token、私钥直接写进 Jenkinsfile
  • Jenkinsfile 尽量放进代码仓库,方便 Code Review、版本管理和回滚。
  • Pipeline 按阶段拆分,例如 CheckoutTestPackageDocker BuildDeploy
  • 测试环境和生产环境分开,生产部署最好增加人工确认。
  • 大型项目尽量让 Controller 负责调度,让不同 Agent 执行具体构建任务。

总结一下,Jenkins 的核心不是某个按钮或某个插件,而是这条思路:

把原本需要人工执行的发布流程

转换成

稳定、可重复、可追踪的自动化 Pipeline

理解了这一点,Jenkins 就不再只是“构建按钮”,而是软件工程自动化体系中的一块基础设施。

Jenkins 入门:从构建任务到 CI/CD 流水线
https://lllirunze.cn/posts/jenkins-guide/
作者
柒月の風灬
发布于
2026-08-29
许可协议
CC BY-NC-SA 4.0