Jenkins 自动打包发布 SpringCloud 微服务项目(含脚本)

发布于:2023-02-04 ⋅ 阅读:(731) ⋅ 点赞:(0)

在这里插入图片描述

环境准备

1. 安装JDK

  • 查看jdk版本
java -version
[root@sinolee /]# java -version
java version "17.0.2" 2022-01-18 LTS
Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)

2. 安装Git

yum install -y git
  • 查看是否安装成功
git version
[root@sinolee /]# git version
git version 1.8.3.1

3. 安装 Maven

yum -y install maven
  • 查看maven版本
mvn -version
[root@sinolee /]# mvn -version
Apache Maven 3.8.4 (9b656c72d54e5bacbed989b64718c159fe39b537)
Maven home: /usr/local/apache-maven-3.8.4
Java version: 17.0.2, vendor: Oracle Corporation, runtime: /usr/java/jdk-17.0.2
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.10.0-1160.66.1.el7.x86_64", arch: "amd64", family: "unix"

4. 安装jenkins

  • yum安装
wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
yum upgrade

异常处理

启动异常 : Jenkins Continuous Integration Server

  • 使用 systemctl start jenkins.service 命令启动可能抛异常:
[root@sinolee ~]# systemctl start jenkins.service
Job for jenkins.service failed because the control process exited with error code. See "systemctl status jenkins.service" and "journalctl -xe" for details.
[root@sinolee ~]# systemctl status jenkins.service
● jenkins.service - Jenkins Continuous Integration Server
   Loaded: loaded (/usr/lib/systemd/system/jenkins.service; disabled; vendor preset: disabled)
   Active: failed (Result: start-limit) since Wed 2022-06-29 15:53:38 CST; 3s ago
  Process: 6449 ExecStart=/usr/bin/jenkins (code=exited, status=1/FAILURE)
 Main PID: 6449 (code=exited, status=1/FAILURE)

Jun 29 15:53:37 sinolee systemd[1]: Failed to start Jenkins Continuous Integration Server.
Jun 29 15:53:37 sinolee systemd[1]: Unit jenkins.service entered failed state.
Jun 29 15:53:37 sinolee systemd[1]: jenkins.service failed.
Jun 29 15:53:38 sinolee systemd[1]: jenkins.service holdoff time over, scheduling restart.
Jun 29 15:53:38 sinolee systemd[1]: Stopped Jenkins Continuous Integration Server.
Jun 29 15:53:38 sinolee systemd[1]: start request repeated too quickly for jenkins.service
Jun 29 15:53:38 sinolee systemd[1]: Failed to start Jenkins Continuous Integration Server.
Jun 29 15:53:38 sinolee systemd[1]: Unit jenkins.service entered failed state.
Jun 29 15:53:38 sinolee systemd[1]: jenkins.service failed.
  • 解决方案:
    • 不使用systemctl的方式操作Jenkins, 直接用Jenkins自带的服务启动 (使用 systemctl 最终也是执行的这个命令)
    • 切换到 Jenkins 脚本目录 cd /etc/init.d, 执行以下命令
# 启动
./jenkins start
# 停止
./jenkins stop
# 状态
./jenkins status

执行结果:

[root@sinolee init.d]# ./jenkins restart
Shutting down Jenkins                                      [  OK  ]
Starting Jenkins                                           [  OK  ]
[root@sinolee init.d]# ./jenkins status
jenkins (pid  19113) is running...

访问 jenkins, 浏览器地址栏输入 主机IP : 端口号, 如:127.0.0.1:8080
在这里插入图片描述

访问异常

在这里插入图片描述

  • 解决方案:
    • 安装以下包
yum install dejavu-sans-fonts
yum install fontconfig
yum install xorg-x11-server-Xvfb

环境配置及插件

定制安装所需插件

  • 配置路径 : Manage Jenkins >>> Manage Plugins

在这里插入图片描述

  • 选择所需插件, 点击安装 ( Install without restart )
    在这里插入图片描述

  • 安装中文插件

    • Available 搜索 ChineseLocalization: Chinese (Simplified)
      在这里插入图片描述

配置全局工具

1. 配置 Java 工具

  • 配置路径 : 系统管理 >>> 全局工具配置 >>> JDK >>> 新增JDK

在这里插入图片描述

注 : 若服务器上没有 Java 环境,可以选择自动安装。
建议 : 请预先在服务器上配置好Java环境. 可参考文章 ( 阿里云 ) Linux 安装jdk1.8(rpm方式)

2. 配置 Maven

  • 配置路径 : 系统管理 >>> 全局工具配置 >>> Maven 配置

在这里插入图片描述

当前配置页下,新增 Maven 安装路径,请手动配置,不选自动安装
在这里插入图片描述

settings.xml 文件 一般都是在 Maven 安装路径的 conf 目录下
建议 : 请预先在服务器上配置好Maven环境. 可参考文章 Linux 配置 Maven

基本使用

任务全部使用传统配置模式

CI 的整体逻辑 : 拉取代码 >>> 设置编译命令(方法) >>> 编译 >>> 生成结果(二进制文件或包)

创建一个Java任务

新建任 >>> 输入任务名称 >>> 构建一个Maven项目

Ps : 没有 构建一个Maven项目 选项的处理办法

在这里插入图片描述

  • 点击 可选插件 输入关键字 : Maven Integration 搜索并安装

在这里插入图片描述

  • 重启jenkins即可看到选项

在这里插入图片描述

源码管理

Ps : Jenkins源码管理无Git选项

在这里插入图片描述

  • 点击 可选插件 输入关键字 : Github 搜索并安装

在这里插入图片描述

配置项目Git账号
在这里插入图片描述

在这里插入图片描述

需构建的代码分支,此处是固定写死的。 当参数化构建的时候,可以填入指定的分支和tag
在这里插入图片描述

构建触发器

在这里插入图片描述

构建环境

在这里插入图片描述

Build

在这里插入图片描述

指定pom.xml的位置,maven类型的任务在编译的时候是根据代码中pom.xml的定义进行代码的编译动作

Post Steps

在这里插入图片描述

构建设置

在这里插入图片描述

构建后操作

可设置编译成功后的操作,如归档、触发其他的任务、清理工作空间,或其他一些自定义的操作。操作依赖插件的支持。在代码编译成功后增加发布的动作即整体实现CD的功能,从代码到服务器

在这里插入图片描述

run.sh 打包脚本

# 项目模块统一变量设置

# 消息队列服务
MQ_CONTAINER="mq"
MQ_IMAGE="mq_server"
MQ_PORT=8081

# 网站服务
WEB_CONTAINER="web"
WEB_IMAGE="web_server"
WEB_PORT=8082

# 用户服务
USER_CONTAINER="user"
USER_IMAGE="user_server"
USER_PORT=8083

echo "========== 删除旧代码 =========="
rm -rf /home/project/demo/*

# 拷贝新代码到应用服务器
echo "========== 拷贝代码 =========="
scp -r ./* /home/project/demo/

# 切换到项目文件夹下
cd /home/project/demo/

echo "========== 项目开始构建打包 =========="
mvn clean package -Dmaven.test.skip=true

echo "========== 拷贝 jar 文件 =========="
mkdir -p /project/demo
\cp -r /home/project/demo/*/target/*server*.jar /project/demo

echo "========== 拷贝 DockerFile 文件 =========="
\cp /home/project/demo/DockerFile /project/demo

# 停止并删除旧的容器
echo "========== 停止并删除旧的容器 =========="
docker ps -a | grep $MQ_CONTAINER && docker stop $MQ_CONTAINER && docker rm $MQ_CONTAINER || echo "mq service not exist"
docker ps -a | grep $WEB_CONTAINER && docker stop $WEB_CONTAINER && docker rm $WEB_CONTAINER || echo "web service not exist"
docker ps -a | grep $USER_CONTAINER && docker stop $USER_CONTAINER && docker rm $USER_CONTAINER || echo "user service not exist"

# 删除旧的镜像
echo "========== 删除旧的镜像 =========="
docker images | grep MQ_IMAGE && docker rmi -f MQ_IMAGE || echo "mq old image not exist"
docker images | grep WEB_IMAGE && docker rmi -f WEB_IMAGE || echo "web old image not exist"
docker images | grep USER_IMAGE && docker rmi -f USER_IMAGE || echo "user old image not exist"

# 构建新的镜像
echo "========== 构建新的镜像 =========="
docker build --build-arg JAR_FILE=mq-server-1.0-SNAPSHOT.jar -t $MQ_IMAGE -f DockerFile /project/demo/
docker build --build-arg JAR_FILE=web-server-1.0-SNAPSHOT.jar -t $WEB_IMAGE -f DockerFile /project/demo/
docker build --build-arg JAR_FILE=user-server-1.0-SNAPSHOT.jar -t $USER_IMAGE -f DockerFile /project/demo/

# 运行镜像容器
echo "========== 运行镜像容器 =========="
docker run -it -d --name $MQ_CONTAINER -p $MQ_PORT:$MQ_PORT $MQ_IMAGE
docker run -it -d --name $WEB_CONTAINER -p $WEB_PORT:$WEB_PORT $WEB_IMAGE
docker run -it -d --name $USER_CONTAINER -p $USER_PORT:$USER_PORT $USER_IMAGE

echo "部署成功"

DockerFile 内容

FROM openjdk:17
ARG JAR_FILE
MAINTAINER cccccc@qq.com # 邮箱
COPY ${JAR_FILE} app.jar
ENV JAVA_OPTS="-Xmx512m -Xms512m -Xmn512m -Xss256K -XX:SurvivorRatio=8 -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m -XX:+UseConcMarkSweepGC -XX:ConcGCThreads=4 -XX:+CMSClassUnloadingEnabled -Dfile.encoding=UTF-8 -XX:+DisableExplicitGC -XX:+PrintGC -XX:+PrintGCTimeStamps -Xloggc:./gc.log"
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

踩坑记录

1. 无法找到 mvn 命令 ( mvn: command not found )

  • Jenkins 构建历史 控制台输出

在这里插入图片描述

  • run.sh 文件, 第46行代码

在这里插入图片描述

  • 服务器项目文件夹下执行 mvn clean package -Dmaven.test.skip=true 可正常打包

  • 原因分析:
    对于java或maven的路径的环境变量是放在/etc/profile中的, 而/etc/profile只有在用户登录的时候才会被load,Jenkins在运行命令时,使用的是Non-login的方式,而这种方式在运行命令时,/etc/profile是不会被load进来的,所以jenkins只能在当前路径下寻找可执行文件

  • 解决方案:
    jenkins (主界面) Dashboard -> (系统管理) Manage Jenkins -> (系统配置) Configure System -> (全局属性) Global Properties -> (环境变量) Environment variables -> (键值对列表) List of variables
    在Jenkins设置全局变量,新增如下内容:

    • JAVA_HOME/usr/java/jdk-17.0.2
    • MAVEN_HOME/usr/local/apache-maven-3.8.4
    • PATH+EXTRA$MAVEN_HOME/bin

JAVA_HOME、MAVEN_HOME 对应的值分别为各自安装目录
PATH+EXTRA 表示 PATH=EXTRA:$PATH, 即扩展当前的PATH变量

在这里插入图片描述

2. 运行失败 ( Exception in thread “main” java.lang.NoClassDefFoundError )

[root@sinolee demo]# docker ps -a
CONTAINER ID   IMAGE                COMMAND                  CREATED              STATUS                          PORTS     NAMES
b7a7addce8bd   user_server            "java -Djava.securit…"   About a minute ago   Exited (1) About a minute ago             es
[root@sinolee linu]# docker logs b7a7addce8bd
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/boot/SpringApplication
        at com.test.demo.UserApplication.main(EsApplication.java:14)
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.SpringApplication
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
        ... 1 more
  • 解决方法 子项目 pom.xml 中新增 build
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.4.11</version>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

3. 一定要注意 SpringBoot SpringCloud SpringCloudAlibaba 之间的版本, 建议别用新版本, 各依赖之间的 jar 包冲突整的人头皮发麻…

本文采用版本
jdk 17
maven 3.8.4
Spring 5.3.20
SpringBoot 2.6.8
SpringCloud 2021.0.3
SpringCloudAlibaba 2021.1

  • 父项目 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.6.8</version>
    </parent>

    <groupId>com.test</groupId>
    <artifactId>demo</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    
    <modules>
        <module>user-service</module>
        <module>web-service</module>
    </modules>

    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
        <spring-cloud.version>2021.0.3</spring-cloud.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring Cloud 依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- SpringCloudAlibaba 依赖 -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

ps:如有错误,欢迎批评指正,谢谢!

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到