Skip to content

单体部署 ​

Linux 单机私有化部署手册(一屏通读,用右侧「本页目录」跳转章节)。主路径:Ubuntu + Docker Compose;备选:JAR + systemd。部署完成后继续看 上线文档。

00 部署方案 ​

适用场景 ​

  • 中小企业 / 单机云主机
  • 同一台机器跑 Nginx + 后端 + MySQL + Redis(可选 OnlyOffice、XXL-Job、Jenkins)

不适用:服务拆分 → 微服务部署;仅有 Windows → Windows 部署。

架构(主路径) ​

text
浏览器 → :80/:443 Nginx
  ├─ /web · /app 静态
  ├─ /admin-api → 127.0.0.1:48080
  └─ /onlyoffice · /cache · /coauthoring → OnlyOffice(可选)
本机:MySQL · Redis · yudao-server
对外:仅 22 + 80(+443)

资源基线 ​

项目最低推荐(含 OnlyOffice)
CPU4 核8 核
内存8 GB16 GB+
磁盘100 GB200 GB+ SSD
OSUbuntu 22.04 / 24.04 LTS同左


操作系统与运行环境 ​

前置检查 ​

  • [ ] 云安全组 / 防火墙仅开放 22、80(需要 HTTPS 再开 443)
  • [ ] 已规划静态公网/内网 IP:<SERVER_IP>
  • [ ] 已准备 sudo 权限账号
  • [ ] 不要在生产机安装 Maven、Node、pnpm(构建在开发机或 Jenkins)

目录约定(推荐) ​

bash
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/appJAR / 后端工作目录
/data/app/upload本地文件存储
/data/nginx/html/webPC 前端静态
/data/nginx/html/app移动端 H5 静态(可选)
/data/composeDocker Compose 与 .env
/data/backup备份

Docker 安装(主路径) ​

Ubuntu 示例:

bash
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 示例) ​

bash
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:3306
  • redis:7(或 6+),端口绑定 127.0.0.1:6379:6379
  • 密码写入 /data/compose/.env(勿提交 Git)
bash
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 部署用) ​

bash
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 ping

JDK 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
AdminDocker xuxueli/xxl-job-admin:2.4.2,宿主机建议 127.0.0.1:9090 → 容器 8080
执行器默认 AppName yudao-server;accessToken 与后端一致(默认 default_token,生产请改)
账号Admin 初始 admin/123456,上线立即改密

1)建库与任务注册(来自 ruoyi-office-db/dump/latest/):

bash
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.sql

2)启动 Admin(MySQL 与 Admin 同机 Docker 时,用宿主机内网 IP 作 JDBC):

bash
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.2

3)后端打开执行器(application-prod.yaml 或外部配置):

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 清单见仓库内 docs/deploy/xxl-job/Docker部署XXL-Job.md(不对外发布)。

可选:其它中间件(按需) ​

组件何时需要备注
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/。自行准备时:

bash
ls ruoyi-office-db/dump/latest/

禁止:直接导入演示站业务过程库(含试用管控、演示账号脏数据)。

建库 ​

sql
CREATE DATABASE IF NOT EXISTS `ruoyi-office`
  DEFAULT CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

导入 ​

Compose MySQL 示例:

bash
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:

bash
mysql -u root -p ruoyi-office < /data/sql/schema.sql
mysql -u root -p ruoyi-office < /data/sql/static_data.sql

验证 ​

bash
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 等表。

文件存储(上线前可先做) ​

本地盘方案:确保目录存在且后端可写:

bash
sudo mkdir -p /data/app/upload
sudo chmod -R 775 /data/app/upload

库中 infra_file_config 主配置需指向该目录与可访问的 domain(详见 上线文档 · 域名与存储)。


对齐已跑通的客户生产形态:容器跑后端,静态文件挂 Nginx(容器或宿主机均可)。
完整 compose 以客户交付包为准;下文给出可执行最小步骤与必对配置。

本地 / 构建机构建 ​

构建与运行分离:在开发机或 Jenkins 打产物,再上传到生产机。本节拆成 后端构建、前端构建、H5 构建(可选)。

环境 ​

软件版本用途
JDK17 或 21后端构建
Maven3.8+后端构建
Node.js≥ 20.19前端 / H5 构建
pnpm≥ 10前端 / H5 构建

后端构建 ​

bash
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 参数请加双引号。

前端构建 ​

PC 管理端(Vben web-antd),产物挂 Nginx /web/。

构建前检查 apps/web-antd/.env.production:

ini
VITE_BASE_URL=
VITE_GLOB_API_URL=/admin-api
VITE_GLOB_DEMO_ENABLE=false
VITE_APP_DOCALERT_ENABLE=false
bash
cd ~/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"。

PC 的 VITE_GLOB_API_URL=/admin-api 是相对路径,由浏览器当前域名经 Nginx 反代,不要套到 UniApp H5 上。

H5 构建(可选) ​

合同含手机浏览器 / 企业微信内打开时才需要。产物挂 Nginx /app/,与 PC /web/ 并列。独立安装包走 Android APK 打包,不是这一步。

构建前改 ruoyi-office-uniapp/env/.env.production(会覆盖 env/.env 同名项):

ini
VITE_APP_PUBLIC_BASE=/app/
VITE_SERVER_BASEURL = 'https://<客户域名>/admin-api'

把 <客户域名> 换成现场入口,例如 oa.example.com。必须带 https://(内网可 http://)的绝对地址。

不要写成相对路径 /admin-api:普通接口还能登录,但 uni.uploadFile 会再拼一层,请求变成 /admin-api/admin-api/infra/file/upload,后端报 No static resource admin-api/admin-api/...。仓库默认值 https://ruoyioffice.com/admin-api 也不要打进客户包。

Docker / Jenkins 的 ENV VITE_SERVER_BASEURL=... 会盖掉文件内容,以最终 JS 产物为准,不要只看源码里的 env。

bash
cd ~/workspace/ruoyi-office-uniapp
pnpm install
pnpm build:h5:prod
ls dist/build/h5/index.html

验收产物:在 dist/build/h5/assets/index-*.js 里应出现 https://<客户域名>/admin-api,不能只是 return"/admin-api"。

VITE_UPLOAD_BASEURL 不是 BPM 附件上传接口,Nginx 也不需要单独的 /upload location。

上传 ​

bash
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/
# 若交付 H5:
scp -r dist/build/h5/* <USER>@<SERVER_IP>:/data/nginx/html/app/

服务器:构建并启动后端容器 ​

示例(按交付包调整镜像名与网络):

bash
cd /data/app
sudo docker build -t yudao-server:latest -f Dockerfile .

Compose 片段要点:

yaml
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
      - redis
bash
cd /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。

前端静态 ​

bash
ls /data/nginx/html/web/index.html
ls /data/nginx/html/app/index.html   # 若交付 H5

Nginx 配置见下文「Nginx 最小配置」(已含 /web、/app、/admin-api)。

启停 ​

bash
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 时使用本路径。

构建与上传 ​

与上文 Docker 路径相同:本地 -P boot 打 JAR,构建 PC dist(可选再打 H5),上传到:

text
/data/app/yudao-server.jar
/usr/share/nginx/html/web/   # 或 /data/nginx/html/web/
/usr/share/nginx/html/app/   # 可选,UniApp H5;或 /data/nginx/html/app/

启动参数 ​

通过环境变量或 -D 覆盖库连接(无需解压 JAR):

bash
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:

ini
[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.target
bash
sudo systemctl daemon-reload
sudo systemctl enable --now yudao-server
sudo systemctl status yudao-server
sudo journalctl -u yudao-server -f

日常更新 ​

bash
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

PC:替换 web/ 静态文件即可,无需重启 Nginx。H5:替换 app/,同样不必重启 Nginx(仅改过 conf 才 reload)。


Nginx 最小配置 ​

先保证能打开 /web 并登录。静态缓存、WebSocket、积木报表、OnlyOffice、商城等完整 location 见 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/;
    }
}
bash
sudo nginx -t && sudo nginx -s reload

若存在 default.conf 同时监听 80,先禁用以免冲突。

OnlyOffice 反代(可选,历史阻断项) ​

安装 Document Server、后端配置与排障见 OnlyOffice 文档服务集成指南。

当 Document Server 跑在 Compose 网络内时:

  1. proxy_pass 必须使用 compose 服务名(如 http://onlyoffice-documentserver/),不要写死 172.17.0.1:8081(自定义网络网关常不是 172.17)。
  2. 除 /onlyoffice/ 外,还需反代 Document Server 根路径资源:/cache/、/coauthoring/。否则浏览器报 Editor.bin 404,编辑器无法打开。
  3. 改完执行 nginx -t 并 reload。

切域名 / HTTPS 时同步改 OnlyOffice server-url 与 infra_file_config.domain,见 上线文档。

验证清单 ​

检查项命令 / 地址预期
后端健康curl -s http://127.0.0.1:48080/actuator/healthUP / 200
前端浏览器 http://<SERVER_IP>/web/登录页
登录账号 admin / 初始密码以库为准(常见 admin123)进入首页
API 经 Nginx登录成功且网络面板无 502通过
移动端 H5(若交付)http://<SERVER_IP>/app/能打开并登录
H5 附件上传(若交付)流程表单上传文件请求是 /admin-api/infra/file/upload,不是 /admin-api/admin-api/...
端口暴露公网扫 3306/6379/48080/8080/8081不可达
上传(若已配本地盘)管理端上传附件文件落入 /data/app/upload

登录成功后立即进入 上线文档:改密、关演示提示、验证码与品牌化。

验收勾选(单体) ​

  • [ ] /web/ 可打开并可登录
  • [ ] (若交付)/app/ 可打开;H5 的 VITE_SERVER_BASEURL 为 https://客户域名/admin-api
  • [ ] /admin-api 经 Nginx 正常
  • [ ] 中间件与后端仅本机可达
  • [ ] (若启用)XXL-Job Admin 本机可达、执行器在线、默认密码已改
  • [ ] 备份策略已安排(mysqldump + upload 目录)
  • [ ] 已阅读并执行上线文档关键项

仅收录历史真实阻断与高频问题。

现象处理
OnlyOffice 打开报错 / Editor.bin 404检查 Nginx:proxy_pass 是否为 compose 服务名;是否反代了 /cache/、/coauthoring/
页面 502 / 504curl 127.0.0.1:48080/actuator/health;看后端日志;确认 proxy_pass 端口
/web 404ls .../web/index.html;alias 路径;是否与 default.conf 冲突;nginx -t && reload
后端立刻退出查 MySQL/Redis 密码与连通;内存是否过小;48080 是否占用
JAR 体积异常大(>500MB 且异常翻倍)构建必须带 -Dskip.repackage=true
前端构建 OOMNODE_OPTIONS=--max-old-space-size=4096
同机 Jenkins 构建卡死 / OOMexecutor=1;构建前临时停 OnlyOffice;限制 Jenkins 堆
登录后仍有「演示环境」横幅VITE_GLOB_DEMO_ENABLE=false 并重建,或改已部署 _app.config.js(见上线文档)
上传失败目录权限;infra_file_config 主配置与 domain
H5 上传报 No static resource admin-api/admin-api/...打包把 VITE_SERVER_BASEURL 写成了相对 /admin-api。改为 https://客户域名/admin-api 后重打;Docker/Jenkins ENV 可能覆盖源码 env。Nginx /admin-api 反代本身不会叠路径

日志位置 ​

组件位置
JAR + systemdjournalctl -u yudao-server -f
Docker 后端docker logs -f yudao-server
Nginx/var/log/nginx/error.log 或容器内日志
联系我们

获取报价、演示和二开方案

微信咨询二维码

微信咨询

17156169080

添加时备注「RuoYi Office」

在线体验商业版