使用 Jenkins 的流水线项目实施 CI/CD

一、Jenkins 环境准备(插件 + 工具配置)

1.安装必要插件

  • 进入 Jenkins Web 界面 → 系统管理插件管理可选插件

  • 搜索并安装:

    • Maven Integration(Maven 项目构建支持)。

    • Publish Over SSH(远程 SSH 部署)。

    • GitLab Plugin(若需 GitLab 触发流水线,可选)。

2.配置 Maven 工具

  • 进入 Jenkins → 系统管理全局工具配置

  • 找到 Maven 区域 → 点击 Maven 安装

    • Name :自定义(如 maven-3.9.6)。

    • 勾选 自动安装版本 选择 3.9.6 → 点击 保存

3.配置 Publish Over SSH(远程部署到 Docker 主机)

  • 进入 Jenkins → 系统管理系统配置
  • 找到 Publish over SSH 区域 → 点击 新增 ,配置 SSH 服务器:
    • Name :自定义(如 DockerHost)。
    • Hostname :Docker 主机的 IP / 域名(如 192.168.197.9)。
    • Username :远程主机用户名(如 root)。
    • Remote Directory :远程部署目录(如 /opt/jenkins_deploy,需提前创建)。
    • 展开 高级 → 勾选 Use password authentication → 输入远程主机 密码 → 点击 Test Configuration(验证显示 Success)→ 应用保存
bash 复制代码
[root@host1 ~]# mkdir -p /opt/jenkins_deploy
[root@host1 ~]# ls -ld /opt/jenkins_deploy
drwxr-xr-x. 2 root root 6  9月 27 23:13 /opt/jenkins_deploy
[root@host1 ~]# 

二、GitLab 与项目代码准备

1.GitLab 新建空白项目

  • 登录 GitLab → New project → 选择 Create blank project

  • 项目名称:java-demo → 点击 Create project

2.克隆仓库到本地并准备代码

bash 复制代码
[root@host1 ch07]# cd ~/ch07
[root@host1 ch07]# git clone ssh://git@gitlab.abc.com:2222/root/java-demo.git
正克隆到 'java-demo'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
接收对象中: 100% (3/3), 完成.
bash 复制代码
[root@host1 ch07]# cd java-demo
[root@host1 java-demo]# cat > Dockerfile << EOF
FROM openjdk:18-jre
ARG app
ADD \$app app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar"]
EOF

三、Jenkins 新建流水线项目

1.新建流水线任务

  • 进入 Jenkins → 新建任务 → 任务名 java-demo → 选择 流水线 → 点击 确定

2.配置源代码管理(关联 GitLab 仓库)

  • 在项目配置页 → 源代码管理 → 选择 Git

    • Repository URL :GitLab 项目的 SSH 地址(如 ssh://git@gitlab.abc.com:2222/root/java-demo.git)。

    • Credentials:选择之前配置的 GitLab SSH 凭据(若未配置,需先添加)。

    • Branches to build :改为 */main(GitLab 新仓库默认分支为 main)。

3.配置流水线(从 Git 拉取 Jenkinsfile

  • Pipeline 区域 → 选择 Pipeline script from SCM

  • SCM 再次选择 Git → 重复仓库和凭据配置 → Script Path 填写 Jenkinsfile保存

四、编写 Jenkinsfile(定义 CI/CD 流程)

java-demo 本地项目目录下,创建 Jenkinsfile,内容如下(需根据实际项目调整变量):

bash 复制代码
[root@host1 ~]# cd ~/ch07
[root@host1 ch07]# cd java-demo
[root@host1 java-demo]# vi Jenkinsfile
[root@host1 java-demo]# cat Jenkinsfile
pipeline {
    agent any
    tools {
        // 关联全局工具配置的 Maven 名称
        maven 'maven-3.9.6'
    }
    stages {
        stage('Build') {
            steps {
                // Maven 编译打包(跳过测试)
                sh 'mvn -B -DskipTests clean package'
            }
        }
        stage('Test') {
            steps {
                // Maven 执行测试
                sh 'mvn test'
            }
            post {
                always {
                    // 生成 JUnit 测试报告
                    junit allowEmptyResults: true, testResults: 'target/surefire-reports/*.xml'
                }
            }
        }
        stage('Docker Build & Push') {
            steps {
                // 构建并推送 Docker 镜像到私有仓库
                sh '''
                    APP_JAR=$(ls target/*.jar | head -1)
                    docker build --build-arg app=$APP_JAR -t registry.abc.com:5000/spring-boot-demo .
                    docker push registry.abc.com:5000/spring-boot-demo
                    docker rmi registry.abc.com:5000/spring-boot-demo
                '''
            }
        }
        stage('Deploy to Docker Host') {
            steps {
                // 通过 Publish Over SSH 远程运行 Docker 容器
                sshPublisher(publishers: [
                    sshPublisherDesc(configName: 'DockerHost', transfers: [
                        sshTransfer(
                            cleanRemote: false,
                            execCommand: '''
                                docker rm -f spring-boot-demo || true
                                docker run -d -p 8080:8080 --name spring-boot-demo \
                                registry.abc.com:5000/spring-boot-demo
                            ''',
                            execTimeout: 120000,
                            sourceFiles: ''
                        )
                    ])
                ])
            }
        }
    }
    environment {
        // 定义环境变量(根据项目实际情况修改)
        REGISTRY_URL = 'registry.abc.com:5000'
        CONTAINER_NAME = 'spring-boot-demo'
        IMAGE_NAME = 'spring-boot-demo'
    }
}

五、提交代码到 GitLab

bash 复制代码
# 添加所有文件到暂存区
[root@host1 java-demo]# git add .

# 提交代码
[root@host1 java-demo]# git commit -m "Init Java project with Jenkins CI/CD"
[main 4c6ffcc] Init Java project with Jenkins CI/CD
 2 files changed, 67 insertions(+)
 create mode 100644 Dockerfile
 create mode 100644 Jenkinsfile

# 推送代码到 GitLab(首次推送需关联分支)
[root@host1 java-demo]# git push --set-upstream origin main
枚举对象中: 5, 完成.
对象计数中: 100% (5/5), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (4/4), 完成.
写入对象中: 100% (4/4), 1.26 KiB | 430.00 KiB/s, 完成.
总共 4(差异 0),复用 0(差异 0),包复用 0(来自  0 个包)
To ssh://gitlab.abc.com:2222/root/java-demo.git
   9434c2c..4c6ffcc  main -> main
分支 'main' 设置为跟踪 'origin/main'。

六、触发 Jenkins 流水线并验证

1.手动触发构建

进入 Jenkins 的 java-demo 项目 → 点击 立即构建

2.查看构建日志

点击构建任务 → 控制台输出,查看各阶段(Build、Test、Docker Build & Push、Deploy)的执行日志。

3.验证部署结果

在 Docker 主机执行以下命令,检查容器运行和应用访问:

bash 复制代码
[root@host1 java-demo]# curl http://192.168.197.9:8080
Hello from Spring Boot via Jenkins! 

七、关键注意事项

  • 确保 registry.abc.com:5000 私有镜像仓库已启动(参考前文 Docker Registry 部署步骤)。

  • Publish Over SSHconfigName 需与系统配置中定义的 SSH 服务器名称一致。

  • Maven 命令、Docker 镜像名、容器端口等需根据实际项目调整。

!!!部分纠错过程:

bash 复制代码
https://maven.aliyun.com/repository/public/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar
Downloaded from aliyunmaven: https://maven.aliyun.com/repository/public/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar (2.2 kB at 1.6 kB/s)
Downloaded from aliyunmaven: https://maven.aliyun.com/repository/public/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.jar (5.9 kB at 4.2 kB/s)
Downloaded from aliyunmaven: https://maven.aliyun.com/repository/public/com/google/j2objc/j2objc-annotations/1.3/j2objc-annotations-1.3.jar (8.8 kB at 5.5 kB/s)
Downloaded from aliyunmaven: https://maven.aliyun.com/repository/public/org/apache/commons/commons-lang3/3.7/commons-lang3-3.7.jar (500 kB at 310 kB/s)
Downloaded from aliyunmaven: https://maven.aliyun.com/repository/public/com/google/guava/guava/28.2-android/guava-28.2-android.jar (2.6 MB at 1.4 MB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  52.768 s
[INFO] Finished at: 2025-09-28T01:31:32+08:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.7.12:repackage (repackage) on project java-demo: Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.7.12:repackage failed: Unable to find main class -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException
[root@host1 java-demo]# vi src/main/java/com/example/demo/DemoApplication.java
[root@host1 java-demo]# cat src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
[root@host1 java-demo]# git add src/main/java/com/example/demo/DemoApplication.java
[root@host1 java-demo]# git commit -m "Add Spring Boot main application class"
[main b7d9a73] Add Spring Boot main application class
 1 file changed, 13 insertions(+)
 create mode 100644 src/main/java/com/example/demo/DemoApplication.java
[root@host1 java-demo]# git push origin main
枚举对象中: 16, 完成.
对象计数中: 100% (16/16), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (4/4), 完成.
写入对象中: 100% (9/9), 732 字节 | 366.00 KiB/s, 完成.
总共 9(差异 1),复用 0(差异 0),包复用 0(来自  0 个包)
To ssh://gitlab.abc.com:2222/root/java-demo.git
   12fe51e..b7d9a73  main -> main
[root@host1 java-demo]# cat pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/>
    </parent>
    <groupId>com.example</groupId>
    <artifactId>java-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>java-demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
相关推荐
斯普信专业组2 小时前
Filebeat写ElasticSearch故障排查思路(下)
运维·elasticsearch·中间件·filebeat
深蓝易网3 小时前
3C电子企业柔性制造转型:如何通过MES管理系统实现快速换线与弹性生产?
大数据·运维·人工智能·重构·制造
Gss7773 小时前
Nginx 反向代理与负载均衡核心内容总结
运维·nginx·负载均衡
安审若无3 小时前
解决 sqlplus / as sysdba 登录缓慢问题
运维·服务器·数据库
szxinmai主板定制专家3 小时前
ZYNQ 平台下的四声道超声流量计设计与实现
运维·arm开发·人工智能·分布式·fpga开发
遥感之家4 小时前
AWS下载sentinel-2原始影像
云计算·sentinel·aws
熙客4 小时前
Jenkins:持续集成和持续交付(CI/CD)工具
运维·ci/cd·jenkins
亚林瓜子4 小时前
AWS中的离线计算(大数据大屏项目)
大数据·hadoop·sql·spark·云计算·aws
AWS官方合作商4 小时前
AWS实战:轻松创建弹性IP,实现固定公网IP地址
tcp/ip·云计算·aws