项目一系列-第10章 项目自动化部署

第10章 项目自动化部署

1. 整体部署思路

在企业正常的项目部署中,可能会涉及多台服务器共同使用,例如Nginx、Tomcat、Redis、MySQL等都会有对应的单独的服务器,让各个服务器进行互相通信即可完成部署。对于学习阶段,所有的服务都可使用同一个虚拟机来完成项目的部署。

  • 微信小程序需要租用腾讯的服务器才能完成部署,但在本示例中不会涉及。
  • 学习环境中,所有服务将部署在同一虚拟机上。

2. 环境准备

2.1 基础环境

以下列出了软件环境及版本,并提供了安装方式:

软件版本安装方式
Docker20.10.11Shell
Docker Compose1.29.1Shell
Java JDK11.0.19Shell
Maven3.6.1Shell
Git1.8.3.1Shell
Redis7.2.4Docker
MySQL8.0.29Docker
Nginx1.25.5Docker

基础环境Shell脚本安装

该shell脚本负责安装Git、Java JDK和Maven。

命名为install.sh。

#!/bin/bash
# 安装 Git
echo "开始安装 Git..."
yum install git -y
echo "Git安装完成"
echo `git --version`

# 下载并安装 JDK 11
echo "开始下载并安装 JDK 11..."
tar -xzf jdk-11.0.21_linux-x64_bin.tar.gz
mv jdk-11.0.21 /usr/local/src/
chmod +x /usr/local/src/jdk-11.0.21/bin/*
# 设置环境变量
echo "export JAVA_HOME=/usr/local/src/jdk-11.0.21" >> /etc/profile
echo "export PATH=\$PATH:\$JAVA_HOME/bin" >> /etc/profile
source /etc/profile
echo `java -version`
echo "JDK 11安装完成"

# 下载并安装 Maven
echo "开始下载并安装 Maven..."
MAVEN_URL="https://dlcdn.apache.org/maven/maven-3/3.8.8/binaries/apache-maven-3.8.8-bin.tar.gz"
cd /usr/local/src
wget $MAVEN_URL
tar -xzf apache-maven-3.8.8-bin.tar.gz
mv apache-maven-3.8.8 /usr/local/src/
echo "Maven安装完成"

# 设置环境变量
echo "export MAVEN_HOME=/usr/local/src/apache-maven-3.8.8" >> /etc/profile
echo "export PATH=\$PATH:\$MAVEN_HOME/bin" >> /etc/profile
source /etc/profile
echo `mvn -version`

echo "JDK 11和Maven安装完成"

创建shell脚本后,执行下面命令获取执行权限:

# 赋予执行权限(修正后的命令)
chmod +x install.sh

# 执行脚本(建议用 sudo 提升权限)
sudo ./install.sh

2.2 Jenkins介绍和安装

Jenkins是一款开源的自动化服务器,广泛用于支持持续集成与持续交付(CI/CD)流程。通过配置Jenkins,可以实现自动化的构建、测试和部署过程。

  • 启动命令: 使用Docker运行docker start jenkins
  • 访问地址: http://192.168.100.168:8000/
  • 用户名: zzyl
  • 密码: itcast

登录后可根据需求创建流水线任务以自动化CI/CD流程。

3. 部署后端项目

3.1 多环境说明

在项目开发和部署过程中,通常会有三套不同的项目环境:

  • Development(开发环境)
  • Production(生产环境)
  • Test(测试环境)

例如,在开发环境中连接的是本地安装的MySQL数据库,而在生产环境中需要连接线上的MySQL环境。

application.ymlapplication-druid.yml合并。合并后的配置文件示例如下:

# 项目相关配置
ruoyi:
  # 名称
  name: RuoYi
  # 版本
  version: 3.8.8
  # 版权年份
  copyrightYear: 2024
  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
  profile: D:/ruoyi/uploadPath
  # 获取ip地址开关
  addressEnabled: false
  # 验证码类型 math 数字计算 char 字符验证
  captchaType: math

# 开发环境配置
server:
  # 服务器的HTTP端口,默认为8080
  port: 8080
  servlet:
    # 应用的访问路径
    context-path: /
  tomcat:
    # tomcat的URI编码
    uri-encoding: UTF-8
    # 连接数满后的排队数,默认为100
    accept-count: 1000
    threads:
      # tomcat最大线程数,默认为200
      max: 800
      # Tomcat启动初始化的线程数,默认值10
      min-spare: 100

# 日志配置
logging:
  level:
    com.zzyl: debug
    org.springframework: warn

# 用户配置
user:
  password:
    # 密码最大错误次数
    maxRetryCount: 5
    # 密码锁定时间(默认10分钟)
    lockTime: 10

# Spring配置
spring:
  # 资源信息
  messages:
    # 国际化资源文件路径
    basename: i18n/messages
  # 文件上传
  servlet:
    multipart:
      # 单个文件大小
      max-file-size: 10MB
      # 设置总上传的文件大小
      max-request-size: 20MB
  # 服务模块
  devtools:
    restart:
      # 热部署开关
      enabled: true
  # redis 配置
  redis:
    # 地址
    host: 192.168.100.168
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 0
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池的最大数据库连接数
        max-active: 8
        # #连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: -1ms
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # 主库数据源
      master:
        url: jdbc:mysql://192.168.100.168:3306/ry-zzyl?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: heima123
      # 从库数据源
      slave:
        # 从数据源开关/默认关闭
        enabled: false
        url:
        username:
        password:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置连接超时时间
      connectTimeout: 30000
      # 配置网络超时时间
      socketTimeout: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # 控制台管理用户名和密码
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true

# token配置
token:
  # 令牌自定义标识
  header: Authorization
  # 令牌密钥
  secret: abcdefghijklmnopqrstuvwxyz
  # 令牌有效期(默认30分钟)
  expireTime: 30

# MyBatis配置
#mybatis:
#  # 搜索指定包别名
#  typeAliasesPackage: com.zzyl.**.domain
#  # 配置mapper的扫描,找到所有的mapper.xml映射文件
#  mapperLocations: classpath*:mapper/**/*Mapper.xml
#  # 加载全局的配置文件
#  configLocation: classpath:mybatis/mybatis-config.xml
# MyBatisPlus配置
mybatis-plus:
  # 搜索指定包别名
  typeAliasesPackage: com.zzyl.**.domain
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # 全局配置
  global-config:
    db-config:
      id-type: auto   #id生成策略为自增
  configuration:
    map-underscore-to-camel-case: true    #字段与属性,自动转换为驼峰命名

# PageHelper分页插件
pagehelper:
  helperDialect: mysql
  supportMethodsArguments: true
  params: count=countSql

# Swagger配置
swagger:
  # 是否开启swagger
  enabled: true
  # 请求前缀
  pathMapping: /dev-api

# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /system/notice
  # 匹配链接
  urlPatterns: /system/*,/monitor/*,/tool/*
oss:
  endpoint: oss-cn-beijing.aliyuncs.com
  accessKeyId: LTAI5tJe9A6bWwhFEkYyaXjD
  accessKeySecret: hLpwmQ6YAS5l0FvsSFuw7aDN3DPNvp
  bucketName: itheim
baidu:
  accessKey: xEO9h4csw91eUrzWlUiYpkNt
  secretKey: T67Xuyx9JoAWt1UEACQcFCVkd2HnZuKH
  qianfanModel: ERNIE-4.0-8K-Preview

根据上述配置,创建三个配置文件以适应不同的环境:

  • application-dev.yml:开发环境
  • application-test.yml:测试环境
  • application-prod.yml:生产环境(注意修改服务端口为9000)

application.yml中设置激活的环境配置:

spring:
  profiles:
    active: prod

3.2 Jenkins 流水线

Jenkins流水线是一种用于定义和执行自动化构建、测试和部署过程的方式。声明式流水线的基本结构如下:

pipeline {  
    agent any // 指定流水线运行的节点,any 表示任何可用的节点  
    stages {  
        stage('Build') { // 定义阶段  
            steps {  
                echo 'Building...'  
            }  
        },
        stage('Test') { // 定义阶段  
            steps {
                echo 'Testing...'  
            }
        },
        stage('Deploy') { // 定义阶段  
            steps {
                echo 'Deploying...'  
            }
        }
    }
}

主要指令和阶段包括:

  • agent: 指定流水线或特定阶段在哪个节点上执行。
  • stages: 包含流水线中的所有阶段(stage),是流水线的主要分组单元。
  • stage: 定义一个阶段,阶段内可以包含一个或多个步骤。
  • steps: 定义在某个阶段内执行的具体操作。
  • post: 在所有阶段完成后执行的操作,基于不同的条件(如成功、失败、总是)来执行。
  • environment: 定义流水线中的环境变量。
  • options: 定义全局选项和配置,如超时设置、并行执行等。
  • parameters: 定义流水线的参数,用于接收用户输入。
  • triggers: 定义触发流水线执行的条件或事件,如定时触发、代码推送触发等。

在后端项目中进行 Jenkins 构建配置

1)在父模块主目录下创建 Jenkinsfile 文件,文件内容如下:

pipeline {
    agent any
    options {
        timestamps()
    }
    tools {
        maven 'maven'
        jdk 'jdk11'
    }
    stages {
        stage('清除工作空间') {
            steps {
                cleanWs()
            }
        }
        stage('拉取Git代码') {
            steps {
                echo "正在拉取代码..."
                echo "当前分支:${GIT_TAG},当前服务:${services}"
                checkout([$class: 'GitSCM',
                          branches: [[name: GIT_TAG]],
                          doGenerateSubmoduleConfigurations: false,
                          extensions: [],
                          submoduleCfg: [],
                          userRemoteConfigs: [[credentialsId: 'Gitee_ID', url: GIT_URL]]
                ])
                sh "pwd"
            }
        }
        stage('重新Maven打包') {
            steps {
                script {
                    echo "正在执行maven打包...."
                    sh "mvn clean install -DskipTests"
                }
            }
        }
        stage('重新构建镜像') {
            steps {
                echo "当前打镜像tag:${DOCKER_TAG}"
                script {
                    for (ds in services.tokenize(",")) {
                         sh "pwd"
                         echo "进入target目录执行镜像打包......"
                         sh "cd ./${ds}/target/ && docker build -t ${ds}:${DOCKER_TAG} -f ../Dockerfile ."
                    }
                }
            }
        }
        stage('部署服务'){
            steps {
                script {
                    for (ws in services.tokenize(",")) {
                        sh "pwd"
                        sh "cd `pwd`"
                        echo "部署升级:${ws}服务"
                        sh "chmod +x ./${ws}/deploy.sh && sh ./${ws}/deploy.sh ${ws} ${DOCKER_TAG}"
                    }
                }
            }
        }

    }
    post {
        always {
            echo '任务构建完毕'
        }
    }
}

2)在admin模块主目录下创建Dockerfile和deploy.sh。

  • Dockerfile
# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENV OSS_ACCESS_KEY_ID LTAI5tFww3VE7EZSs9dfh7j5
ENV OSS_ACCESS_KEY_SECRET 3eVYBbuK1F8rX5Tv0ge8lkKG1TrOLs
# 拷贝jar包
COPY zzyl-admin.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]

要记得改为你自己的OSS密钥。

  • deploy.sh
#!/bin/bash
# 容器名称
container_name=$1
# 镜像名称
image_name=$1
# 镜像tag
image_tag=$2

# 判断容器是否存在
if docker ps -a | grep $container_name | awk '{print $1}'; then
  echo "容器 $container_name 存在"
  if docker ps | grep $container_name | awk '{print $1}';then
     echo "关闭正在运行的容器 $container_name"
     docker stop `docker ps | grep $container_name | awk '{print $1}'`
  else
    echo "容器 $container_name 都已关闭"
  fi
  # 删除容器
  echo "删除容器 $container_name"
  docker rm `docker ps -a | grep $container_name | awk '{print $1}'`
else
  echo "容器 $container_name 不存在"
fi

# 启动容器
echo "启动容器 $container_name"
if [ $container_name = "zzyl-admin" ]; then
    docker run -d --restart=always --name $container_name -v /usr/local/zzyl-admin/logs:/home/ruoyi/logs -p 9000:9000 $image_name:$image_tag
fi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值