宇擎后端单体部署指南
项目信息
- 项目名称: RuoYi Office 后端服务
- 技术栈: Spring Boot 3.5.9 + MyBatis Plus + Redis + MySQL
- Java 版本: JDK 17+(Docker 镜像使用 Eclipse Temurin 21)
- 构建工具: Maven 3.8+
- 服务端口: 48080
部署架构
Jenkins服务器(192.168.30.140) 目标服务器(192.168.30.130)
┌─────────────────────┐ ┌──────────────────────────┐
│ Jenkins容器 │ │ Docker │
│ - 拉取代码 │ SSH传输JAR │ ┌────────────────────┐ │
│ - Maven 构建 │ ─────────────> │ │ MySQL 8.0 │ │
│ - 生成 JAR │ │ │ - 端口: 3306 │ │
│ │ │ │ - 数据库: ruoyi- │ │
└─────────────────────┘ │ │ office │ │
│ └────────────────────┘ │
│ ┌────────────────────┐ │
│ │ Redis 7.x │ │
│ │ - 端口: 6379 │ │
│ └────────────────────┘ │
│ ┌────────────────────┐ │
│ │ yudao-server │ │
│ │ - 端口: 48080 │ │
│ └────────────────────┘ │
└──────────────────────────┘前置条件
- Jenkins 服务器(140)已部署并运行
- 目标服务器(130)已安装 Docker
- 两台服务器之间网络互通
- Jenkins 可以访问 Git 仓库
部署步骤
步骤1: 配置 SSH 免密登录
在 Jenkins 服务器(140)上执行:
# 进入 Jenkins 容器
docker exec -it jenkins bash
# 生成 SSH 密钥(如果已有密钥可跳过)
# 方式1: 使用默认名称 id_rsa
ssh-keygen -t rsa -b 4096 -C "jenkins@140" -f ~/.ssh/id_rsa -N ""
# 方式2: 使用自定义名称(如 jenkins_rsa)
# ssh-keygen -t rsa -b 4096 -C "jenkins@140" -f ~/.ssh/jenkins_rsa -N ""
# 将公钥复制到目标服务器
# 如果使用默认名称 id_rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.30.130
# 如果使用自定义名称 jenkins_rsa
# ssh-copy-id -i ~/.ssh/jenkins_rsa.pub root@192.168.30.130
# 测试连接
# 如果使用默认私钥
ssh root@192.168.30.130 'echo "SSH连接成功"'
# 如果使用指定私钥
#ssh -i ~/.ssh/jenkins_rsa root@192.168.30.130 'echo "SSH连接成功"'
# 退出容器
exit说明: ssh-copy-id 会将公钥添加到目标服务器的 /root/.ssh/authorized_keys 文件中。
如果 ssh-copy-id 执行后仍然需要输入密码,请按以下步骤排查:
1.1 检查公钥是否已复制
# 在 Jenkins 容器中查看公钥内容
cat ~/.ssh/id_rsa.pub
# 在目标服务器(130)上检查 authorized_keys
ssh root@192.168.30.130 "cat ~/.ssh/authorized_keys"如果 authorized_keys 文件不存在或为空,手动复制公钥:
# 方式1: 使用 ssh-copy-id(推荐,会自动处理权限)
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.30.130
# 方式2: 手动复制(如果方式1失败)
# 在 Jenkins 容器中执行
cat ~/.ssh/id_rsa.pub | ssh root@192.168.30.130 "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"1.2 检查目标服务器权限
在目标服务器(130)上执行:
# 检查 .ssh 目录权限(必须是 700)
ls -ld ~/.ssh
chmod 700 ~/.ssh
# 检查 authorized_keys 文件权限(必须是 600)
ls -l ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
# 检查文件所有者(必须是 root)
ls -l ~/.ssh/authorized_keys
chown root:root ~/.ssh/authorized_keys1.3 检查 SSH 服务配置
在目标服务器(130)上检查 SSH 配置:
# 检查 SSH 配置
grep -E "PubkeyAuthentication|AuthorizedKeysFile|PasswordAuthentication" /etc/ssh/sshd_config
# 应该看到:
# PubkeyAuthentication yes
# AuthorizedKeysFile .ssh/authorized_keys
# PasswordAuthentication yes(可选,建议保留作为备用)
# 如果配置被禁用,修改后重启 SSH 服务
sed -i 's/#PubkeyAuthentication no/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/PubkeyAuthentication no/PubkeyAuthentication yes/' /etc/ssh/sshd_config
systemctl restart sshd1.4 使用详细模式测试连接
在 Jenkins 容器中执行:
# 使用 -v 参数查看详细连接信息
ssh -v root@192.168.30.130 'echo "SSH连接成功"'
# 查看具体失败原因,常见问题:
# - Permission denied (publickey) - 公钥未正确配置
# - Host key verification failed - 需要添加 -o StrictHostKeyChecking=no1.5 验证免密登录
成功配置后,应该不需要输入密码:
# 测试连接(应该直接成功,不需要输入密码)
ssh -o StrictHostKeyChecking=no root@192.168.30.130 'echo "SSH免密登录成功"'从宿主机获取私钥(用于 Jenkins 凭据配置):
# Jenkins 容器挂载了 /opt/jenkins_home:/var/jenkins_home
# 在宿主机上查看私钥(根据实际密钥名称选择)
# 如果使用默认名称 id_rsa
cat /opt/jenkins_home/.ssh/id_rsa
# 如果使用自定义名称 jenkins_rsa
cat /opt/jenkins_home/.ssh/jenkins_rsa
# 或者从容器内查看
docker exec jenkins cat ~/.ssh/jenkins_rsa步骤2: 在目标服务器部署 MySQL
在目标服务器(192.168.30.130)上执行:
注意: 如果目标服务器上还没有 MySQL Docker 镜像,需要先拉取镜像。docker run 命令会自动拉取镜像,但建议先手动拉取以验证网络连接。
2.1 创建数据目录和配置
# 创建 MySQL 数据目录
mkdir -p /data/mysql/data
mkdir -p /data/mysql/conf
mkdir -p /data/mysql/init
# 创建 MySQL 配置文件
cat > /data/mysql/conf/my.cnf << 'EOF'
[mysqld]
# 基础配置
port=3306
datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
pid-file=/var/run/mysqld/mysqld.pid
# 字符集配置
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
# 认证方式(兼容旧客户端)
default-authentication-plugin=mysql_native_password
# 大小写不敏感
lower_case_table_names=1
# 时间配置
explicit_defaults_for_timestamp=true
# 连接配置
max_connections=500
max_connect_errors=1000
# 缓存配置
innodb_buffer_pool_size=512M
innodb_log_file_size=256M
# 日志配置
slow_query_log=1
slow_query_log_file=/var/lib/mysql/slow.log
long_query_time=2
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
EOF2.2 配置 Docker 镜像加速器(推荐)
如果无法从 Docker Hub 拉取镜像,建议先配置国内镜像加速器:
在目标服务器(192.168.30.130)上执行:
# 创建或编辑 Docker daemon 配置文件
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
EOF
# 重新加载 Docker 配置
systemctl daemon-reload
systemctl restart docker
# 验证配置是否生效
docker info | grep -A 10 "Registry Mirrors"说明:
- 配置镜像加速器后,
docker pull命令会自动使用加速器 - 如果某个镜像源不可用,Docker 会自动尝试下一个
- 配置后需要重启 Docker 服务
2.3 拉取 MySQL 镜像
在目标服务器(192.168.30.130)上执行:
方式1: 使用镜像加速器拉取(推荐)
# 配置镜像加速器后,直接拉取官方镜像
docker pull mysql:8.0.33
# 验证镜像是否拉取成功
docker images | grep mysql方式2: 使用国内镜像源(如果方式1失败)
# 使用华为云镜像源
docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:8.0.33
docker tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/mysql:8.0.33 mysql:8.0.33
# 使用阿里云镜像源(需要先登录,或使用公开镜像)
docker pull registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0.33
docker tag registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0.33 mysql:8.0.33
# 或使用网易镜像源
docker pull hub.c.163.com/library/mysql:8.0.33
docker tag hub.c.163.com/library/mysql:8.0.33 mysql:8.0.33
# 或使用腾讯云镜像源
docker pull ccr.ccs.tencentyun.com/library/mysql:8.0.33
docker tag ccr.ccs.tencentyun.com/library/mysql:8.0.33 mysql:8.0.33方式3: 手动下载镜像文件(如果网络完全不通)
# 在有网络的机器上下载镜像并导出
# docker pull mysql:8.0.33
# docker save mysql:8.0.33 -o mysql-8.0.33.tar
# 传输到目标服务器后导入
# scp mysql-8.0.33.tar root@192.168.30.130:/tmp/
# docker load -i /tmp/mysql-8.0.33.tar说明:
- 如果本地已有 MySQL 镜像,可以跳过此步骤
docker run命令执行时,如果本地没有镜像会自动拉取,但先拉取可以提前验证网络连接- 镜像大小约 500MB,根据网络速度可能需要几分钟
2.4 启动 MySQL 容器
docker run -d \
--name mysql \
--restart always \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD='Admin$123!' \
-e MYSQL_DATABASE=ruoyi-office \
-v /data/mysql/data:/var/lib/mysql \
-v /data/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf \
-v /data/mysql/init:/docker-entrypoint-initdb.d \
mysql:8.0.33重要: 请将 Admin$123! 替换为您的强密码。
说明:
- 如果本地没有 MySQL 镜像,
docker run会自动拉取,但可能需要较长时间 - 建议先执行
docker pull确保镜像下载成功
2.5 验证 MySQL 启动
# 等待容器启动(约 30 秒)
sleep 30
# 检查容器状态
docker ps | grep mysql
# 测试连接(密码包含特殊字符时使用单引号)
docker exec -it mysql mysql -uroot -p'YourStrongPassword123!' -e "SELECT VERSION();"
# 查看数据库
docker exec -it mysql mysql -uroot -p'YourStrongPassword123!' -e "SHOW DATABASES;"步骤3: 在目标服务器部署 Redis
在目标服务器(192.168.30.130)上执行:
注意: 如果目标服务器上还没有 Redis Docker 镜像,需要先拉取镜像。docker run 命令会自动拉取镜像,但建议先手动拉取以验证网络连接。
3.1 创建 Redis 数据目录和配置
# 创建 Redis 数据目录
mkdir -p /data/redis/data
mkdir -p /data/redis/conf
# 创建 Redis 配置文件
cat > /data/redis/conf/redis.conf << 'EOF'
# 绑定地址(允许所有IP访问,生产环境建议限制)
bind 0.0.0.0
# 端口
port 6379
# 密码(生产环境强烈建议设置)
# requirepass YourRedisPassword123!
# 持久化配置
appendonly yes
appendfsync everysec
# 内存限制(根据服务器内存调整)
maxmemory 512mb
maxmemory-policy allkeys-lru
# 日志级别
loglevel notice
# 数据目录
dir /data
# 后台运行(Docker 中不需要)
daemonize no
# 超时配置
timeout 300
tcp-keepalive 300
EOF3.2 拉取 Redis 镜像
在目标服务器(192.168.30.130)上执行:
注意: 如果已在步骤 2.2 配置了 Docker 镜像加速器,可以直接使用方式1。如果未配置或方式1失败,请使用方式2。
方式1: 使用镜像加速器拉取(推荐)
# 如果已配置镜像加速器,直接拉取官方镜像
docker pull redis:7.2
docker pull swr.cn-south-1.myhuaweicloud.com/library/redis:latest
docker tag swr.cn-south-1.myhuaweicloud.com/library/redis:latest redis:latest
# 验证镜像是否拉取成功
docker images | grep redis方式2: 使用国内镜像源(如果方式1失败)
# 使用阿里云镜像源
docker pull registry.cn-hangzhou.aliyuncs.com/library/redis:7.2
docker tag registry.cn-hangzhou.aliyuncs.com/library/redis:7.2 redis:7.2
# 或使用网易镜像源
docker pull hub.c.163.com/library/redis:7.2
docker tag hub.c.163.com/library/redis:7.2 redis:7.2
# 或使用腾讯云镜像源
docker pull ccr.ccs.tencentyun.com/library/redis:7.2
docker tag ccr.ccs.tencentyun.com/library/redis:7.2 redis:7.2方式3: 手动下载镜像文件(如果网络完全不通)
# 在有网络的机器上下载镜像并导出
# docker pull redis:7.2
# docker save redis:7.2 -o redis-7.2.tar
# 传输到目标服务器后导入
# scp redis-7.2.tar root@192.168.30.130:/tmp/
# docker load -i /tmp/redis-7.2.tar说明:
- 如果本地已有 Redis 镜像,可以跳过此步骤
docker run命令执行时,如果本地没有镜像会自动拉取,但先拉取可以提前验证网络连接- 镜像大小约 100MB,根据网络速度可能需要几分钟
3.3 启动 Redis 容器
docker run -d \
--name redis \
--restart always \
-p 6379:6379 \
-v /data/redis/data:/data \
-v /data/redis/conf/redis.conf:/etc/redis/redis.conf \
redis:latest \
redis-server /etc/redis/redis.conf说明:
- 如果本地没有 Redis 镜像,
docker run会自动拉取,但可能需要较长时间 - 建议先执行
docker pull确保镜像下载成功
3.4 验证 Redis 启动
# 检查容器状态
docker ps | grep redis
# 测试连接
docker exec -it redis redis-cli ping
# 应该返回 PONG
# 测试读写
docker exec -it redis redis-cli SET test "Hello Redis"
docker exec -it redis redis-cli GET test步骤4: 初始化数据库
4.1 上传 SQL 脚本
将项目中的 SQL 脚本上传到目标服务器:
# 在本地执行(将 SQL 文件上传到目标服务器)
scp ruoyi-office/sql/mysql/ruoyi-vue-pro.sql root@192.168.30.130:/data/mysql/init/
scp ruoyi-office/sql/mysql/quartz.sql root@192.168.30.130:/data/mysql/init/
# 如果有其他业务 SQL,也需要上传
# scp ruoyi-office/sql/mysql/*.sql root@192.168.30.130:/data/mysql/init/4.2 执行 SQL 脚本
# 在目标服务器上执行
# 导入主数据库脚本(密码包含特殊字符时使用单引号)
docker exec -i mysql mysql -uroot -p'Admin$123!' ruoyi-office < /data/mysql/init/dump-ruoyi-office-202601221629.sql
docker exec -i mysql mysql -uroot -p'YourStrongPassword123!' ruoyi-office < /data/mysql/init/ruoyi-vue-pro.sql
# 导入 Quartz 调度表(如果使用定时任务)
docker exec -i mysql mysql -uroot -p'YourStrongPassword123!' ruoyi-office < /data/mysql/init/quartz.sql4.3 验证数据库初始化
# 查看表数量(密码包含特殊字符时使用单引号)
docker exec -it mysql mysql -uroot -p'Admin$123!' -e "USE ruoyi-office; SHOW TABLES;" | wc -l
# 查看系统用户表
docker exec -it mysql mysql -uroot -p'Admin$123!' -e "USE ruoyi-office; SELECT id, username FROM system_users LIMIT 5;"步骤5: 配置 Jenkins
5.1 安装必要插件
进入 Jenkins管理 -> 插件管理 -> 可选插件,安装以下插件:
- Maven Integration Plugin - Maven 构建支持
- SSH Agent Plugin - SSH 连接支持
- Publish Over SSH - 文件传输(可选,推荐)
安装后重启 Jenkins:
docker restart jenkins5.2 配置 JDK 工具
方式1: 使用 Adoptium (Eclipse Temurin) - 推荐
如果 Jenkins 支持 Install from adoptium.net 选项:
- 进入
Jenkins管理->全局工具配置 - 找到
JDK部分,点击新增JDK - 配置:
- 名称:
jdk17 - JAVA_HOME: 留空(自动安装)
- 勾选
自动安装 - 选择
Install from adoptium.net->jdk-17.x
- 名称:
如果看不到 Install from adoptium.net 选项,请使用方式2或方式3。
方式2: 手动指定 JDK 路径(推荐,最可靠)
如果 Jenkins 不支持自动安装或只能选择到 JDK 9,可以手动安装 JDK 17 后指定路径:
步骤1: 在 Jenkins 容器中安装 JDK 17
# 进入 Jenkins 容器
docker exec -it jenkins bash
# 下载并安装 OpenJDK 17(Adoptium)
cd /tmp
# 方式1: 使用清华大学镜像源(推荐,速度快)
wget https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
curl -O https://mirrors.tuna.tsinghua.edu.cn/Adoptium/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.17_10.tar.gz
# 方式2: 使用华为云镜像源(备选)
# wget https://mirrors.huaweicloud.com/java/jdk/17.0.13+11/jdk-17.0.13_linux-x64_bin.tar.gz
# 方式3: 使用腾讯云镜像源(备选)
# wget https://mirrors.cloud.tencent.com/AdoptOpenJDK/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# 方式4: 如果国内镜像源都不可用,使用官方源(较慢)
# wget https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.13%2B11/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# 如果 wget 不可用,使用 curl(替换上面的 wget 命令)
# curl -L -o OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# curl -L -o OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz https://mirrors.cloud.tencent.com/AdoptOpenJDK/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# 解压
tar -xzf OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# 移动到 /opt 目录
mv jdk-17.0.13+11 /opt/jdk17
# 没权限切换root mv
docker exec -u root -it jenkins bash
# 验证安装
/opt/jdk17/bin/java -version
# 退出容器
exit步骤2: 在 Jenkins 中配置 JDK 路径
- 进入
Jenkins管理->全局工具配置 - 找到
JDK部分,点击新增JDK - 配置:
- 名称:
jdk17 - JAVA_HOME:
/opt/jdk17(手动输入路径) - 不要勾选
自动安装
- 名称:
- 点击
保存
方式3: 在宿主机安装 JDK 17,挂载到容器
如果不想在容器内安装,可以在宿主机安装后挂载:
步骤1: 在宿主机安装 JDK 17
# 在 Jenkins 服务器(140)的宿主机上执行
cd /opt
# 使用清华大学镜像源(推荐)
wget https://mirrors.tuna.tsinghua.edu.cn/AdoptOpenJDK/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# 或使用华为云镜像源
# wget https://mirrors.huaweicloud.com/java/jdk/17.0.13+11/jdk-17.0.13_linux-x64_bin.tar.gz
# 或使用腾讯云镜像源
# wget https://mirrors.cloud.tencent.com/AdoptOpenJDK/17/jdk/x64/linux/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
# 解压并安装
tar -xzf OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
mv jdk-17.0.13+11 /opt/jdk17
# 验证安装
/opt/jdk17/bin/java -version步骤2: 修改 Jenkins 容器启动命令,挂载 JDK
# 停止并删除现有容器
docker stop jenkins
docker rm jenkins
# 使用新命令启动(添加 JDK 挂载)
docker run --restart always \
--network jenkins \
--name jenkins \
-d -p 8080:8080 -p 50000:50000 \
-v /opt/jenkins_home:/var/jenkins_home \
-v /opt/jdk17:/opt/jdk17 \
jenkins/jenkins
# 等待容器启动
sleep 10步骤3: 在 Jenkins 中配置 JDK 路径
- 进入
Jenkins管理->全局工具配置 - 找到
JDK部分,点击新增JDK - 配置:
- 名称:
jdk17 - JAVA_HOME:
/opt/jdk17 - 不要勾选
自动安装
- 名称:
- 点击
保存
方式4: 更新 Jenkins JDK Plugin(如果版本较旧)
如果 Jenkins 版本较旧,可能需要更新插件:
- 进入
Jenkins管理->插件管理->已安装 - 搜索
JDK Tool Plugin - 如果有更新,点击更新
- 重启 Jenkins:
docker restart jenkins - 重新尝试方式1
推荐: 使用方式2(在容器内手动安装),最简单可靠。
5.3 配置 Maven 工具
- 在
全局工具配置中找到Maven部分 - 点击
新增Maven - 配置:
- 名称:
maven3 - 勾选
自动安装 - 选择版本
3.9.x或更高
- 名称:
5.4 配置 SSH 凭据
- 进入
Jenkins管理->凭据管理->系统->全局凭据 - 点击
添加凭据 - 配置:
- 类型:
SSH Username with private key - ID:
server-130-ssh - 描述:
目标服务器130 SSH凭据 - 用户名:
root - 私钥: 选择
Enter directly,粘贴步骤1中获取的私钥内容
- 类型:
私钥格式要求:
- 必须包含完整的
-----BEGIN ... PRIVATE KEY-----和-----END ... PRIVATE KEY----- - 行之间不能有空行
- 建议使用
cat /opt/jenkins_home/.ssh/id_rsa | grep -v '^$'获取无空行的私钥
5.5 配置 Publish Over SSH(推荐)
进入
Jenkins管理->系统配置找到
Publish over SSH部分点击
新增,配置:- Name:
server-130 - Hostname:
192.168.30.130 - Username:
root - Remote Directory:
/data/app - Use password authentication, or use a different key: 勾选
- Key: 粘贴私钥内容
- Name:
点击
Test Configuration验证连接点击
保存
步骤6: 创建应用部署目录
在目标服务器(192.168.30.130)上执行:
# 创建应用目录
mkdir -p /data/app/yudao-server
mkdir -p /data/app/logs
# 设置权限
chmod 755 /data/app/yudao-server
chmod 755 /data/app/logs步骤7: 创建 Jenkins Pipeline 任务
- 登录 Jenkins Web 界面
- 点击
新建任务 - 输入任务名称:
ruoyi-office-backend-deploy - 选择
流水线(Pipeline) - 点击
确定 - 在配置页面:
- Pipeline 定义: 选择
Pipeline script from SCM - SCM: 选择
Git - Repository URL:
git@codeup.aliyun.com:676b69e335730943ed494c52/ruoyi-office/ruoyi-office.git - Credentials: 选择可以访问 Git 仓库的凭据
- 分支:
*/main或*/master - 脚本路径:
yudao-server/Jenkinsfile
- Pipeline 定义: 选择
- 点击
保存
步骤8: 执行首次部署
- 在 Jenkins 任务页面,点击
立即构建 - 查看构建日志,确认各阶段正常:
- ✅ 拉取代码
- ✅ Maven 构建
- ✅ 传输 JAR 文件
- ✅ 构建 Docker 镜像
- ✅ 启动容器
- ✅ 健康检查
步骤9: 验证部署
9.1 检查容器状态
# 在目标服务器上执行
docker ps | grep yudao-server
# 查看容器日志
docker logs -f yudao-server --tail 1009.2 访问 API 接口
# 健康检查
curl http://192.168.30.130:48080/actuator/health
# 访问 Swagger 文档
# 浏览器打开: http://192.168.30.130:48080/swagger-ui/index.html
# 测试登录接口
curl -X POST http://192.168.30.130:48080/admin-api/system/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'9.3 检查日志
# 查看应用日志
docker logs yudao-server --tail 200
# 查看持久化日志(如果配置了)
tail -f /data/app/logs/yudao-server.log故障排查
SSH 免密登录失败
问题: 执行 ssh root@192.168.30.130 时仍然需要输入密码
原因: SSH 免密登录配置未成功,可能的原因:
- 公钥未正确复制到目标服务器
- 目标服务器文件权限不正确
- SSH 服务配置禁用了公钥认证
- 公钥格式错误
排查步骤:
步骤1: 检查公钥是否已复制
# 在 Jenkins 容器中查看公钥
docker exec -it jenkins cat ~/.ssh/id_rsa.pub
# 在目标服务器上检查 authorized_keys
ssh root@192.168.30.130 "cat ~/.ssh/authorized_keys"如果 authorized_keys 为空或不存在,手动复制:
# 在 Jenkins 容器中执行
docker exec -it jenkins bash
cat ~/.ssh/id_rsa.pub | ssh root@192.168.30.130 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"步骤2: 检查目标服务器权限
在目标服务器(130)上执行:
# 检查并修复权限
ls -ld ~/.ssh
chmod 700 ~/.ssh
ls -l ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
chown root:root ~/.ssh/authorized_keys正确的权限应该是:
drwx------ root root .ssh
-rw------- root root .ssh/authorized_keys步骤3: 检查 SSH 服务配置
在目标服务器(130)上执行:
# 检查 SSH 配置
grep -E "^PubkeyAuthentication|^AuthorizedKeysFile|^PasswordAuthentication" /etc/ssh/sshd_config
# 应该看到:
# PubkeyAuthentication yes
# AuthorizedKeysFile .ssh/authorized_keys
# 如果 PubkeyAuthentication 是 no,修改并重启
sed -i 's/^PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/^#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
systemctl restart sshd步骤4: 使用详细模式诊断
# 在 Jenkins 容器中执行,查看详细连接信息
docker exec -it jenkins ssh -v root@192.168.30.130 'echo "test"'
# 查看关键信息:
# - debug1: Offering public key - 说明正在尝试使用公钥
# - debug1: Server accepts key - 说明服务器接受了公钥
# - Permission denied (publickey) - 说明公钥认证失败步骤5: 验证免密登录
# 在 Jenkins 容器中测试(应该不需要输入密码)
docker exec -it jenkins ssh -o StrictHostKeyChecking=no root@192.168.30.130 'echo "SSH免密登录成功"'常见错误及解决方案:
| 错误信息 | 原因 | 解决方案 |
|---|---|---|
Permission denied (publickey) | 公钥未配置或权限错误 | 检查 authorized_keys 和文件权限 |
Host key verification failed | 首次连接需要确认主机密钥 | 使用 -o StrictHostKeyChecking=no |
Could not resolve hostname | 网络不通或 DNS 问题 | 检查网络连接和 hosts 文件 |
Connection refused | SSH 服务未运行 | 检查 systemctl status sshd |
Docker 镜像拉取失败
问题: 执行 docker pull 时出现网络错误,无法拉取镜像
常见错误:
read tcp: connection reset by peer- 网络连接被重置manifest unknown- 镜像不存在或路径错误Get "https://registry-1.docker.io/v2/": net/http: TLS handshake timeout- 网络超时
解决方案:
方案1: 配置 Docker 镜像加速器(推荐)
# 创建或编辑 Docker daemon 配置文件
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
EOF
# 重新加载并重启 Docker
systemctl daemon-reload
systemctl restart docker
# 验证配置
docker info | grep -A 10 "Registry Mirrors"方案2: 使用国内镜像源直接拉取
# MySQL 镜像
docker pull registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0.33
docker tag registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0.33 mysql:8.0.33
# Redis 镜像
docker pull registry.cn-hangzhou.aliyuncs.com/library/redis:7.2
docker tag registry.cn-hangzhou.aliyuncs.com/library/redis:7.2 redis:7.2其他可用的镜像源:
| 镜像源 | MySQL 路径 | Redis 路径 |
|---|---|---|
| 阿里云 | registry.cn-hangzhou.aliyuncs.com/library/mysql:8.0.33 | registry.cn-hangzhou.aliyuncs.com/library/redis:7.2 |
| 网易 | hub.c.163.com/library/mysql:8.0.33 | hub.c.163.com/library/redis:7.2 |
| 腾讯云 | ccr.ccs.tencentyun.com/library/mysql:8.0.33 | ccr.ccs.tencentyun.com/library/redis:7.2 |
| 中科大 | docker.mirrors.ustc.edu.cn/library/mysql:8.0.33 | docker.mirrors.ustc.edu.cn/library/redis:7.2 |
方案3: 手动导入镜像(网络完全不通时)
# 在有网络的机器上导出镜像
docker pull mysql:8.0.33
docker save mysql:8.0.33 -o mysql-8.0.33.tar
docker pull redis:7.2
docker save redis:7.2 -o redis-7.2.tar
# 传输到目标服务器
scp mysql-8.0.33.tar redis-7.2.tar root@192.168.30.130:/tmp/
# 在目标服务器上导入
docker load -i /tmp/mysql-8.0.33.tar
docker load -i /tmp/redis-7.2.tar方案4: 检查网络和防火墙
# 测试网络连接
ping registry-1.docker.io
ping docker.mirrors.ustc.edu.cn
# 检查防火墙规则
firewall-cmd --list-all
iptables -L -n
# 如果需要,临时关闭防火墙测试
systemctl stop firewalld
# 测试完成后记得重新开启
systemctl start firewalld推荐顺序: 先尝试方案1(配置镜像加速器),如果失败再尝试方案2(直接使用国内镜像源)。
Docker 构建时基础镜像拉取失败
问题: 构建应用镜像时,无法拉取基础镜像 eclipse-temurin:21-jre
错误信息:
ERROR: failed to do request: Head "https://docker.mirrors.ustc.edu.cn/v2/library/eclipse-temurin/manifests/21-jre?ns=docker.io":
dial tcp: lookup docker.mirrors.ustc.edu.cn on 114.114.114.114:53: no such host原因:
- DNS 解析失败
- 镜像加速器配置问题
- 基础镜像不在镜像加速器的缓存中
解决方案:
方案1: 在目标服务器上手动拉取基础镜像(推荐)
在目标服务器(130)上执行:
使用不需要登录的公共镜像源(推荐):
docker pull docker.xuanyuan.run/library/eclipse-temurin:21-jre
# 方式1: 使用中科大镜像源(推荐,不需要登录)
docker pull docker.mirrors.ustc.edu.cn/library/eclipse-temurin:21-jre
docker tag docker.mirrors.ustc.edu.cn/library/eclipse-temurin:21-jre eclipse-temurin:21-jre
# 方式2: 使用网易镜像源(备选)
docker pull hub.c.163.com/library/eclipse-temurin:21-jre
docker tag hub.c.163.com/library/eclipse-temurin:21-jre eclipse-temurin:21-jre
# 方式3: 使用腾讯云镜像源(备选)
docker pull ccr.ccs.tencentyun.com/library/eclipse-temurin:21-jre
docker tag ccr.ccs.tencentyun.com/library/eclipse-temurin:21-jre eclipse-temurin:21-jre
# 验证
docker images | grep eclipse-temurin如果镜像源需要登录(如 xxx.xuanyuan.run):
# 1. 先登录镜像仓库
docker login xxx.xuanyuan.run
# 输入用户名和密码
# 2. 拉取镜像
docker pull xxx.xuanyuan.run/library/eclipse-temurin:21-jre
docker tag xxx.xuanyuan.run/library/eclipse-temurin:21-jre eclipse-temurin:21-jre
# 3. 验证
docker images | grep eclipse-temurin注意: 如果镜像源需要登录但您没有账号,建议使用不需要登录的公共镜像源(中科大、网易、腾讯云等)。
方案2: 修改 Dockerfile 使用国内镜像源(如果方案1失败)
修改 yudao-server/Dockerfile:
# 使用国内镜像源的基础镜像
FROM docker.mirrors.ustc.edu.cn/library/eclipse-temurin:21-jre
# 或者使用网易镜像源
# FROM hub.c.163.com/library/eclipse-temurin:21-jre注意: 这种方式需要修改代码,如果镜像源地址变更需要再次修改。
方案3: 检查并修复 DNS 配置
如果出现 no such host 错误,可能是 DNS 配置问题:
# 检查 DNS 配置
cat /etc/resolv.conf
# 临时修改 DNS(如果当前 DNS 不可用)
echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 114.114.114.114" >> /etc/resolv.conf
# 测试 DNS 解析
nslookup docker.mirrors.ustc.edu.cn
ping docker.mirrors.ustc.edu.cn方案4: 使用 Jenkinsfile 自动拉取(已更新)
Jenkinsfile 已更新,会在构建镜像前自动拉取基础镜像。如果仍然失败,请先手动执行方案1。
推荐: 使用方案1,在目标服务器上手动拉取基础镜像,这是最可靠的方法。
密码包含特殊字符的处理
问题: 如果密码包含特殊字符(如 !、$、& 等),bash 可能会进行历史扩展或命令替换,导致命令执行失败。
解决方案:
在命令行中使用单引号包裹密码:
bash# 错误示例(感叹号会被 bash 解释) docker exec -it mysql mysql -uroot -pYourStrongPassword123! -e "SELECT 1;" # 正确示例(使用单引号) docker exec -it mysql mysql -uroot -p'YourStrongPassword123!' -e "SELECT 1;"在 Docker 环境变量中使用单引号:
bash# 错误示例 -e MYSQL_ROOT_PASSWORD=YourStrongPassword123! # 正确示例 -e MYSQL_ROOT_PASSWORD='YourStrongPassword123!'在 SSH 命令中使用单引号包裹整个命令:
bash# 错误示例(感叹号会被 bash 解释) ssh root@192.168.30.130 "echo 'SSH连接成功!'" # 正确示例(使用单引号包裹整个命令) ssh root@192.168.30.130 'echo "SSH连接成功"'或者使用 -p 参数后不跟密码(会提示输入):
bash# 交互式输入密码(最安全) docker exec -it mysql mysql -uroot -p -e "SELECT 1;"
MySQL 连接失败
问题: 应用无法连接 MySQL
排查步骤:
# 1. 检查 MySQL 容器状态
docker ps | grep mysql
docker logs mysql --tail 50
# 2. 检查网络连通性
docker exec yudao-server ping mysql -c 3
# 3. 检查数据库用户权限(密码包含特殊字符时使用单引号)
docker exec -it mysql mysql -uroot -p'YourStrongPassword123!' -e "SELECT user, host FROM mysql.user;"
# 4. 检查防火墙
firewall-cmd --list-ports解决方案:
# 如果需要允许远程连接(密码包含特殊字符时使用单引号)
docker exec -it mysql mysql -uroot -p'YourStrongPassword123!' -e "
CREATE USER 'root'@'%' IDENTIFIED BY 'YourStrongPassword123!';
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;
"Redis 连接失败
问题: 应用无法连接 Redis
排查步骤:
# 1. 检查 Redis 容器状态
docker ps | grep redis
docker logs redis --tail 50
# 2. 测试 Redis 连接
docker exec -it redis redis-cli ping
# 3. 检查 Redis 配置
docker exec -it redis cat /etc/redis/redis.conf | grep -E "bind|port|requirepass"应用启动失败
问题: yudao-server 容器启动后立即退出
排查步骤:
# 1. 查看容器日志
docker logs yudao-server
# 2. 检查 JVM 参数
docker inspect yudao-server | grep -A 10 "Env"
# 3. 检查内存
free -h
docker stats --no-stream
# 4. 尝试交互式启动排查
docker run -it --rm \
-e "SPRING_PROFILES_ACTIVE=prod" \
yudao-server:latest \
java -jar app.jar端口被占用
问题: 端口 48080 已被占用
解决方案:
# 查看端口占用
netstat -tlnp | grep 48080
lsof -i :48080
# 停止占用端口的进程
kill -9 <PID>
# 或修改应用端口
docker run -d -p 48081:48080 ...内存不足
问题: 应用因 OOM 被 Kill
解决方案:
# 1. 检查服务器内存
free -h
# 2. 调整 JVM 参数(在 docker run 时)
docker run -d \
-e "JAVA_OPTS=-Xms256m -Xmx512m" \
...
# 3. 调整 Docker 内存限制
docker run -d \
--memory=1g \
--memory-swap=2g \
...后续维护
自动触发部署
配置 Git Webhook 实现代码推送自动部署:
- 在 Git 仓库设置中添加 Webhook
- Webhook URL:
http://192.168.30.140:8080/job/ruoyi-office-backend-deploy/build - 触发事件:
Push events
手动触发部署
在 Jenkins 任务页面点击 立即构建。
查看部署历史
在 Jenkins 任务页面可以查看所有构建历史和日志。
数据库备份
# 备份数据库(密码包含特殊字符时使用单引号)
docker exec mysql mysqldump -uroot -p'YourStrongPassword123!' ruoyi-office > /data/backup/ruoyi-office_$(date +%Y%m%d).sql
# 定时备份(添加到 crontab,密码使用单引号包裹)
0 2 * * * docker exec mysql mysqldump -uroot -p'YourStrongPassword123!' ruoyi-office > /data/backup/ruoyi-office_$(date +\%Y\%m\%d).sql日志清理
# 清理 30 天前的日志
find /data/app/logs -name "*.log" -mtime +30 -delete
# 清理 Docker 日志
docker system prune -f配置文件说明
| 文件 | 说明 |
|---|---|
yudao-server/Jenkinsfile | Jenkins Pipeline 配置 |
yudao-server/Dockerfile | Docker 镜像构建配置 |
yudao-server/src/main/resources/application-prod.yaml | 生产环境配置 |
yudao-server/docker-compose.yml | Docker 编排配置(可选) |
安全建议
- 数据库密码: 使用强密码,不要使用默认密码
- Redis 密码: 生产环境建议设置 Redis 密码
- 防火墙: 只开放必要端口(48080),数据库端口不对外开放
- HTTPS: 建议配置 HTTPS 访问
- 日志脱敏: 敏感信息不要打印到日志
- 定期更新: 定期更新 Docker 镜像和依赖
性能优化
JVM 参数优化
根据服务器内存调整:
| 服务器内存 | 推荐 JVM 参数 |
|---|---|
| 2GB | -Xms256m -Xmx512m |
| 4GB | -Xms512m -Xmx1024m |
| 8GB | -Xms1g -Xmx2g |
| 16GB | -Xms2g -Xmx4g |
MySQL 优化
# 根据服务器内存调整 innodb_buffer_pool_size
# 建议设置为总内存的 50-70%Redis 优化
# 根据数据量调整 maxmemory
# 建议设置为总内存的 10-20%常见问题
Q: 如何回滚到上一个版本?
# 1. 查看可用镜像
docker images | grep yudao-server
# 2. 停止当前容器
docker stop yudao-server
docker rm yudao-server
# 3. 使用上一个版本的镜像启动
docker run -d --name yudao-server ... yudao-server:previous_tagQ: 如何查看应用配置?
# 查看激活的配置文件
docker exec yudao-server env | grep SPRING_PROFILES_ACTIVE
# 查看 actuator 配置信息
curl http://192.168.30.130:48080/actuator/envQ: 如何修改配置不重新构建?
# 1. 挂载外部配置文件
docker run -d \
-v /data/app/config/application-prod.yaml:/yudao-server/config/application-prod.yaml \
...
# 2. 使用环境变量覆盖
docker run -d \
-e "SPRING_DATASOURCE_URL=jdbc:mysql://..." \
...快速参考
常用命令
# 查看所有容器
docker ps -a
# 重启应用
docker restart yudao-server
# 查看日志
docker logs -f yudao-server --tail 100
# 进入容器
docker exec -it yudao-server bash
# 查看资源使用
docker stats服务地址
| 服务 | 地址 |
|---|---|
| 后端 API | http://192.168.30.130:48080 |
| Swagger 文档 | http://192.168.30.130:48080/swagger-ui/index.html |
| Druid 监控 | http://192.168.30.130:48080/druid |
| Actuator | http://192.168.30.130:48080/actuator |
默认账号
| 账号 | 密码 | 说明 |
|---|---|---|
| admin | admin123 | 超级管理员 |
