单体部署
Linux 单机私有化部署手册(一屏通读,用右侧「本页目录」跳转章节)。主路径:Ubuntu + Docker Compose;备选:JAR + systemd。部署完成后继续看 上线文档。
00 部署方案
适用场景
- 中小企业 / 单机云主机
- 同一台机器跑 Nginx + 后端 + MySQL + Redis(可选 OnlyOffice、XXL-Job、Jenkins)
不适用:服务拆分 → 微服务部署;仅有 Windows → Windows 部署。
架构(主路径)
浏览器 → :80/:443 Nginx
├─ /web · /app 静态
├─ /admin-api → 127.0.0.1:48080
└─ /onlyoffice · /cache · /coauthoring → OnlyOffice(可选)
本机:MySQL · Redis · yudao-server
对外:仅 22 + 80(+443)资源基线
| 项目 | 最低 | 推荐(含 OnlyOffice) |
|---|---|---|
| CPU | 4 核 | 8 核 |
| 内存 | 8 GB | 16 GB+ |
| 磁盘 | 100 GB | 200 GB+ SSD |
| OS | Ubuntu 22.04 / 24.04 LTS | 同左 |
操作系统与运行环境
前置检查
- [ ] 云安全组 / 防火墙仅开放
22、80(需要 HTTPS 再开443) - [ ] 已规划静态公网/内网 IP:
<SERVER_IP> - [ ] 已准备 sudo 权限账号
- [ ] 不要在生产机安装 Maven、Node、pnpm(构建在开发机或 Jenkins)
目录约定(推荐)
sudo mkdir -p /data/{app,nginx/html/web,nginx/html/app,nginx/conf/conf.d,compose,mysql,redis,scripts,backup}
sudo mkdir -p /data/app/upload| 路径 | 用途 |
|---|---|
/data/app | JAR / 后端工作目录 |
/data/app/upload | 本地文件存储 |
/data/nginx/html/web | PC 前端静态 |
/data/compose | Docker Compose 与 .env |
/data/backup | 备份 |
Docker 安装(主路径)
Ubuntu 示例:
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable --now docker
docker --version
docker compose version预期:打印 Docker 与 Compose 版本号。
防火墙(UFW 示例)
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw enable
sudo ufw status确认云厂商安全组与 UFW 一致:3306/6379/48080/8080/8081 不对公网。
中间件安装
主路径:Compose 拉起 MySQL + Redis
在交付包或自建 docker-compose.yml 中至少包含:
mysql:8,数据卷/data/mysql,端口绑定127.0.0.1:3306:3306redis:7(或 6+),端口绑定127.0.0.1:6379:6379- 密码写入
/data/compose/.env(勿提交 Git)
cd /data/compose
sudo docker compose --env-file .env up -d mysql redis
sudo docker compose ps
sudo docker exec mysql mysqladmin ping -uroot -p"$MYSQL_ROOT_PASSWORD"预期:mysqld is alive;redis-cli -a ... ping 返回 PONG。
客户有偿部署时,直接使用交付目录中的 compose(如
领先/compose/)即可,勿混用演示环境 IP。
备选路径:系统包安装(JAR 部署用)
sudo apt update
sudo apt install -y openjdk-21-jdk mysql-server redis-server nginx
sudo systemctl enable --now mysql redis-server nginx
java -version
mysql -u root -p -e "SELECT VERSION();"
redis-cli pingJDK 17 同样可用。生产服务器装 JDK 仅用于跑 JAR;仍不必装 Maven。
可选:OnlyOffice Document Server
- 以 Compose 服务部署,监听绑本机(如
127.0.0.1:8081) - Nginx 反代必须用 compose 服务名,并覆盖
/onlyoffice/、/cache/、/coauthoring/(详见下文 Nginx / OnlyOffice 节) - 与 Jenkins 同机时注意内存争用(构建前可临时停 OO)
可选:XXL-Job(定时任务调度)
合同含考勤打卡生成、支付/订单过期、日志清理等定时任务时再部署。不装不影响登录与大部分 CRUD;本地 xxl.job.enabled 常为 false。
| 项 | 约定 |
|---|---|
| 库 | 独立库 xxl_job,切勿导入业务库 ruoyi-office |
| Admin | Docker xuxueli/xxl-job-admin:2.4.0,宿主机建议 127.0.0.1:9090 → 容器 8080 |
| 执行器 | 默认 AppName yudao-server;accessToken 与后端一致(默认 default_token,生产请改) |
| 账号 | Admin 初始 admin/123456,上线立即改密 |
1)建库与任务注册(来自 ruoyi-office-db/dump/latest/):
mysql -h 127.0.0.1 -P 3306 -uroot -p < xxl_job_schema.sql
# 全功能版:
mysql -h 127.0.0.1 -P 3306 -uroot -p < xxl_job_init_all.sql
# OA 商业版(勿用 all,避免注册已裁剪模块任务):
# mysql ... < xxl_job_init_oa.sql2)启动 Admin(MySQL 与 Admin 同机 Docker 时,用宿主机内网 IP 作 JDBC):
mkdir -p /data/xxl-job/logs
HOST_IP=$(hostname -I | awk '{print $1}')
docker run -d --name xxl-job-admin --restart always \
-p 127.0.0.1:9090:8080 \
-v /data/xxl-job/logs:/data/applogs \
-e TZ=Asia/Shanghai \
-e PARAMS="--spring.datasource.url=jdbc:mysql://${HOST_IP}:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai --spring.datasource.username=root --spring.datasource.password=<DB_PASSWORD> --xxl.job.accessToken=default_token --xxl.job.logretentiondays=30" \
xuxueli/xxl-job-admin:2.4.03)后端打开执行器(application-prod.yaml 或外部配置):
xxl:
job:
enabled: true
admin:
addresses: http://127.0.0.1:9090/xxl-job-admin验证:浏览器仅经隧道或本机打开 http://127.0.0.1:9090/xxl-job-admin;执行器列表出现在线;9090 不对公网。更细步骤与 JobHandler 清单见 Docker 部署 XXL-Job。
可选:其它中间件(按需)
| 组件 | 何时需要 | 备注 |
|---|---|---|
| RocketMQ | 强依赖 MQ 的业务/事件总线 | 未装时启动可能有连接警告,核心登录通常仍可用 |
| Jenkins | 持续构建发布 | 见 Jenkins 流水线 |
| OSS / MinIO | 文件不上本地盘 | 见 上线文档 · 存储 |
准备 SQL
权威来源:ruoyi-office-db/dump/latest/
| 文件 | 用途 |
|---|---|
schema.sql(或等价全量 schema) | 表结构 |
static_data.sql | 菜单、字典、权限等静态配置 |
客户交付包常提供 scripts/prepare-sql.sh,从 dump 生成 sql/ready/。自行准备时:
ls ruoyi-office-db/dump/latest/禁止:直接导入演示站业务过程库(含试用管控、演示账号脏数据)。
建库
CREATE DATABASE IF NOT EXISTS `ruoyi-office`
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;导入
Compose MySQL 示例:
sudo docker exec -i mysql mysql -uroot -p'<DB_PASSWORD>' ruoyi-office < /data/sql/schema.sql
sudo docker exec -i mysql mysql -uroot -p'<DB_PASSWORD>' ruoyi-office < /data/sql/static_data.sql系统包 MySQL:
mysql -u root -p ruoyi-office < /data/sql/schema.sql
mysql -u root -p ruoyi-office < /data/sql/static_data.sql验证
mysql -u root -p -e "USE \`ruoyi-office\`; SHOW TABLES;" | wc -l
mysql -u root -p -e "USE \`ruoyi-office\`; SELECT id,username FROM system_users LIMIT 5;"预期:能看到 admin 等系统用户;存在 system_menu、system_tenant 等表。
文件存储(上线前可先做)
本地盘方案:确保目录存在且后端可写:
sudo mkdir -p /data/app/upload
sudo chmod -R 775 /data/app/upload库中 infra_file_config 主配置需指向该目录与可访问的 domain(详见 上线文档 · 域名与存储)。
对齐已跑通的客户生产形态:容器跑后端,静态文件挂 Nginx(容器或宿主机均可)。
完整 compose 以客户交付包为准;下文给出可执行最小步骤与必对配置。
本地 / 构建机构建
环境
| 软件 | 版本 |
|---|---|
| JDK | 17 或 21 |
| Maven | 3.8+ |
| Node.js | ≥ 20.19 |
| pnpm | ≥ 10 |
后端(单体)
cd ~/workspace/ruoyi-office
mvn clean package "-Dmaven.test.skip=true" "-Dskip.repackage=true" -pl yudao-server -am -Pboot
ls -lh yudao-server/target/yudao-server.jar关键:-Pboot、-Dskip.repackage=true、-pl yudao-server -am。PowerShell 中 -D 参数请加双引号。
前端
构建前检查 apps/web-antd/.env.production:
VITE_BASE_URL=
VITE_GLOB_API_URL=/admin-api
VITE_GLOB_DEMO_ENABLE=false
VITE_APP_DOCALERT_ENABLE=falsecd ~/workspace/ruoyi-office-vben
pnpm install
pnpm -r --filter "./packages/**" --filter "./internal/**" build
cd apps/web-antd && pnpm build内存不足:export NODE_OPTIONS="--max-old-space-size=4096"。
上传
scp yudao-server/target/yudao-server.jar <USER>@<SERVER_IP>:/data/app/
scp -r apps/web-antd/dist/* <USER>@<SERVER_IP>:/data/nginx/html/web/服务器:构建并启动后端容器
示例(按交付包调整镜像名与网络):
cd /data/app
sudo docker build -t yudao-server:latest -f Dockerfile .Compose 片段要点:
services:
yudao-server:
image: yudao-server:latest
restart: always
mem_limit: 5g
environment:
SPRING_PROFILES_ACTIVE: prod
JAVA_OPTS: "-Xms2g -Xmx4g"
MYSQL_URL: "jdbc:mysql://mysql:3306/ruoyi-office?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true"
MYSQL_USERNAME: root
MYSQL_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: "${REDIS_PASSWORD}"
ports:
- "127.0.0.1:48080:48080"
volumes:
- /data/app/upload:/data/app/upload
depends_on:
- mysql
- rediscd /data/compose
sudo docker compose --env-file .env up -d yudao-server
sudo docker logs -f yudao-server # 等到 Started
curl -s http://127.0.0.1:48080/actuator/health预期:{"status":"UP"} 或 HTTP 200。
前端静态
ls /data/nginx/html/web/index.htmlNginx 配置见 05。
启停
cd /data/compose
sudo docker compose --env-file .env stop yudao-server
sudo docker compose --env-file .env up -d yudao-server有 Jenkins 时,后端 Job 通常:构建 JAR → docker build → compose up -d 重建容器;健康检查走容器网 http://yudao-server:48080/actuator/health。
服务器不使用 Docker、直接装 JDK/MySQL/Redis/Nginx 时使用本路径。
构建与上传
与 03 Docker 路径 相同:本地 -P boot 打 JAR,构建前端 dist,上传到:
/data/app/yudao-server.jar
/usr/share/nginx/html/web/ # 或 /data/nginx/html/web/启动参数
通过环境变量或 -D 覆盖库连接(无需解压 JAR):
nohup java -Xms512m -Xmx2048m \
-DMYSQL_URL="jdbc:mysql://127.0.0.1:3306/ruoyi-office?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true" \
-DMYSQL_USERNAME=root \
-DMYSQL_PASSWORD='<DB_PASSWORD>' \
-DREDIS_HOST=127.0.0.1 \
-DREDIS_PORT=6379 \
-DREDIS_PASSWORD='<REDIS_PASSWORD>' \
-jar /data/app/yudao-server.jar \
--spring.profiles.active=prod \
> /data/app/nohup.out 2>&1 &
tail -f /data/app/nohup.out
curl -s http://127.0.0.1:48080/actuator/health预期:日志出现 Started ...Application;health 返回 UP。
systemd(推荐)
创建 /etc/systemd/system/yudao-server.service:
[Unit]
Description=YuDao Server
After=network.target mysql.service redis.service
[Service]
Type=simple
User=root
WorkingDirectory=/data/app
Environment="MYSQL_URL=jdbc:mysql://127.0.0.1:3306/ruoyi-office?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true"
Environment="MYSQL_USERNAME=root"
Environment="MYSQL_PASSWORD=<DB_PASSWORD>"
Environment="REDIS_HOST=127.0.0.1"
Environment="REDIS_PORT=6379"
Environment="REDIS_PASSWORD=<REDIS_PASSWORD>"
ExecStart=/usr/bin/java -Xms512m -Xmx2048m -jar /data/app/yudao-server.jar --spring.profiles.active=prod
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now yudao-server
sudo systemctl status yudao-server
sudo journalctl -u yudao-server -f日常更新
mvn clean package "-Dmaven.test.skip=true" "-Dskip.repackage=true" -pl yudao-server -am -Pboot
scp yudao-server/target/yudao-server.jar <USER>@<SERVER_IP>:/data/app/
sudo systemctl restart yudao-server前端:替换 web/ 静态文件即可,无需重启 Nginx。
Nginx 最小配置
server {
listen 80;
server_name _;
charset utf-8;
location /web {
alias /data/nginx/html/web;
index index.html;
try_files $uri $uri/ /web/index.html;
}
location /app {
alias /data/nginx/html/app;
index index.html;
try_files $uri $uri/ /app/index.html;
}
location /admin-api {
proxy_pass http://127.0.0.1:48080/admin-api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
location = / {
return 302 /web/;
}
}sudo nginx -t && sudo nginx -s reload若存在
default.conf同时监听 80,先禁用以免冲突。
OnlyOffice 反代(可选,历史阻断项)
当 Document Server 跑在 Compose 网络内时:
proxy_pass必须使用 compose 服务名(如http://onlyoffice-documentserver/),不要写死172.17.0.1:8081(自定义网络网关常不是 172.17)。- 除
/onlyoffice/外,还需反代 Document Server 根路径资源:/cache/、/coauthoring/。否则浏览器报 Editor.bin 404,编辑器无法打开。 - 改完执行
nginx -t并 reload。
切域名 / HTTPS 时同步改 OnlyOffice server-url 与 infra_file_config.domain,见 上线文档。
验证清单
| 检查项 | 命令 / 地址 | 预期 |
|---|---|---|
| 后端健康 | curl -s http://127.0.0.1:48080/actuator/health | UP / 200 |
| 前端 | 浏览器 http://<SERVER_IP>/web/ | 登录页 |
| 登录 | 账号 admin / 初始密码以库为准(常见 admin123) | 进入首页 |
| API 经 Nginx | 登录成功且网络面板无 502 | 通过 |
| 端口暴露 | 公网扫 3306/6379/48080/8080/8081 | 不可达 |
| 上传(若已配本地盘) | 管理端上传附件 | 文件落入 /data/app/upload |
登录成功后立即进入 上线文档:改密、关演示提示、验证码与品牌化。
验收勾选(单体)
- [ ]
/web/可打开并可登录 - [ ]
/admin-api经 Nginx 正常 - [ ] 中间件与后端仅本机可达
- [ ] (若启用)XXL-Job Admin 本机可达、执行器在线、默认密码已改
- [ ] 备份策略已安排(mysqldump + upload 目录)
- [ ] 已阅读并执行上线文档关键项
仅收录历史真实阻断与高频问题。
| 现象 | 处理 |
|---|---|
| OnlyOffice 打开报错 / Editor.bin 404 | 检查 Nginx:proxy_pass 是否为 compose 服务名;是否反代了 /cache/、/coauthoring/ |
| 页面 502 / 504 | curl 127.0.0.1:48080/actuator/health;看后端日志;确认 proxy_pass 端口 |
/web 404 | ls .../web/index.html;alias 路径;是否与 default.conf 冲突;nginx -t && reload |
| 后端立刻退出 | 查 MySQL/Redis 密码与连通;内存是否过小;48080 是否占用 |
| JAR 体积异常大(>500MB 且异常翻倍) | 构建必须带 -Dskip.repackage=true |
| 前端构建 OOM | NODE_OPTIONS=--max-old-space-size=4096 |
| 同机 Jenkins 构建卡死 / OOM | executor=1;构建前临时停 OnlyOffice;限制 Jenkins 堆 |
| 登录后仍有「演示环境」横幅 | VITE_GLOB_DEMO_ENABLE=false 并重建,或改已部署 _app.config.js(见上线文档) |
| 上传失败 | 目录权限;infra_file_config 主配置与 domain |
日志位置
| 组件 | 位置 |
|---|---|
| JAR + systemd | journalctl -u yudao-server -f |
| Docker 后端 | docker logs -f yudao-server |
| Nginx | /var/log/nginx/error.log 或容器内日志 |
