Skip to content

Docker 部署指南

使用 Docker 容器化部署全部服务(MySQL、Redis、后端、Nginx),适合追求环境一致性和快速部署的场景。

如需传统 JAR 包方式部署,请参考 普通部署指南


一、整体流程

本地/构建机                              生产服务器(仅需 Docker)
┌──────────────────┐                ┌──────────────────────────┐
│ 1. 拉取代码       │                │ 3. 安装 Docker            │
│ 2. 构建后端+前端   │  ── 上传产物 ──▶ │ 4. 部署 MySQL + Redis     │
│    (JAR + dist)  │                │ 5. 初始化数据库            │
└──────────────────┘                │ 6. 部署后端(Docker 镜像)  │
                                    │ 7. 部署前端(Nginx 容器)   │
                                    └──────────────────────────┘

⚠️ 不建议在生产服务器上执行构建。构建过程消耗大量 CPU 和内存,且需要安装 Maven、Node.js 等工具链,会污染生产环境。请在本地开发机或专用构建机上完成构建,仅将产物上传到服务器。


二、本地构建(开发机 / 构建机)

以下操作在本地开发机或构建机上执行,不在生产服务器上操作。

2.1 构建环境要求

软件版本要求用途
JDK17 或 21编译后端
Maven3.8+构建后端项目
Node.js≥ 20.19.0构建前端项目
pnpm≥ 10.0.0前端包管理器
Git2.x拉取代码

2.2 拉取代码

bash
mkdir -p ~/workspace && cd ~/workspace

git clone <后端仓库地> ruoyi-office
git clone <前端仓库地> ruoyi-office-vben

2.3 构建后端

bash
cd ~/workspace/ruoyi-office

mvn clean package -Dmaven.test.skip=true -Dskip.repackage=true -pl yudao-server -am -Pprod

# 确认产物
ls -lh yudao-server/target/yudao-server.jar

⚠️ 关键参数

  • -Dskip.repackage=true:子模块跳过 repackage,由 yudao-server 统一打 Fat JAR
  • -pl yudao-server -am:仅构建 yudao-server 及其依赖
  • -Pprod:激活生产环境 Profile

首次构建需下载依赖,约 5-15 分钟。

💡 Maven 国内加速:编辑 $MAVEN_HOME/conf/settings.xml,在 <mirrors> 中添加:

xml
<mirror>
    <id>aliyun</id>
    <mirrorOf>central</mirrorOf>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>

2.4 构建前端

bash
cd ~/workspace/ruoyi-office-vben

# 1. 安装依赖
pnpm install

# 2. 构建 Monorepo 内部依赖包
pnpm -r --filter "./packages/**" --filter "./internal/**" build

# 3. 构建前端应用
cd apps/web-antd
pnpm build

构建产物位于 apps/web-antd/dist/

💡 内存不足报 OOM?执行 export NODE_OPTIONS="--max-old-space-size=4096" 后重试。

💡 vite.config.mts 已配置生产环境 base: '/web/',无需额外修改。

2.5 上传产物到服务器

bash
# 在服务器上预先创建目录
ssh root@服务器IP "mkdir -p /data/app/yudao-server/target /data/nginx/html/web /data/"

# 上传后端 JAR 和 Dockerfile
scp ~/workspace/ruoyi-office/yudao-server/target/yudao-server.jar root@服务器IP:/data/app/yudao-server/target/
scp ~/workspace/ruoyi-office/yudao-server/Dockerfile root@服务器IP:/data/app/yudao-server/

# 上传前端产物
scp -r ~/workspace/ruoyi-office-vben/apps/web-antd/dist/* root@服务器IP:/data/nginx/html/web/

# 上传数据库 SQL(首次部署时需要)
scp ~/workspace/ruoyi-office-db/ruoyi-office-20260301.sql root@服务器IP:/data/

也可使用 FTP、rsync 或其他文件传输方式,效果相同。


三、安装 Docker(生产服务器)

以下所有操作均在生产服务器上执行。生产服务器只需要安装 Docker,不需要 Maven、Node.js 等构建工具。

3.1 服务器配置要求

项目最低配置推荐配置
CPU2 核4 核+
内存4 GB8 GB+
磁盘40 GB100 GB+
操作系统CentOS 7+ / Ubuntu 20.04+CentOS Stream 9 / Ubuntu 22.04

3.2 端口规划

服务端口容器名
Nginx80nginx
yudao-server48080yudao-server
MySQL3306mysql
Redis6379redis

3.3 安装 Docker

bash
# ==================== CentOS / RHEL ====================
yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce docker-ce-cli containerd.io
systemctl start docker && systemctl enable docker

# ==================== Ubuntu / Debian ====================
apt-get update
apt-get install -y ca-certificates curl
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io

3.4 配置镜像加速(推荐)

bash
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}
EOF
systemctl daemon-reload && systemctl restart docker

3.5 验证

bash
docker --version
docker compose version

四、部署 MySQL

4.1 创建目录和配置

bash
mkdir -p /data/mysql/{data,conf}

cat > /data/mysql/conf/my.cnf << 'EOF'
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
default-authentication-plugin=mysql_native_password
lower_case_table_names=1
max_connections=500
innodb_buffer_pool_size=512M

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4
EOF

4.2 启动容器

bash
docker run -d \
  --name mysql \
  --restart always \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD='YourPassword123!' \
  -v /data/mysql/data:/var/lib/mysql \
  -v /data/mysql/conf/my.cnf:/etc/mysql/conf.d/my.cnf \
  mysql:8.0.33

4.3 验证

bash
sleep 20
docker exec -it mysql mysql -uroot -p'YourPassword123!' -e "SELECT VERSION();"

五、部署 Redis

5.1 创建目录和配置

bash
mkdir -p /data/redis/{data,conf}

cat > /data/redis/conf/redis.conf << 'EOF'
bind 0.0.0.0
port 6379
appendonly yes
maxmemory 512mb
maxmemory-policy allkeys-lru
dir /data
EOF

5.2 启动容器

bash
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:7.2 \
  redis-server /etc/redis/redis.conf

5.3 验证

bash
docker exec -it redis redis-cli ping
# 返回 PONG

六、初始化数据库

6.1 创建数据库

bash
docker exec -it mysql mysql -uroot -p'YourPassword123!' -e \
  "CREATE DATABASE IF NOT EXISTS \`ruoyi-office\` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

6.2 导入数据

bash
# SQL 文件已在 2.5 步上传到 /data/ 目录
docker exec -i mysql mysql -uroot -p'YourPassword123!' ruoyi-office < /data/ruoyi-office-20260301.sql

6.3 验证

bash
docker exec -it mysql mysql -uroot -p'YourPassword123!' -e "USE ruoyi-office; SHOW TABLES;" | head -20
# 能看到 system_users 等表即成功

七、部署后端

7.1 确认文件

bash
# JAR 和 Dockerfile 已在 2.5 步上传
ls -lh /data/app/yudao-server/target/yudao-server.jar
ls -lh /data/app/yudao-server/Dockerfile

项目自带 Dockerfile(yudao-server/Dockerfile),基于 eclipse-temurin:21-jre

dockerfile
FROM eclipse-temurin:21-jre
RUN mkdir -p /yudao-server
WORKDIR /yudao-server
COPY ./target/yudao-server.jar app.jar
ENV TZ=Asia/Shanghai
ENV JAVA_OPTS="-Xms1024m -Xmx4096m -Djava.security.egd=file:/dev/./urandom"
ENV ARGS=""
EXPOSE 48080
CMD java ${JAVA_OPTS} -jar app.jar $ARGS

7.2 构建镜像

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

7.3 获取宿主机 IP

容器内不能用 127.0.0.1 访问宿主机上的 MySQL / Redis,需要使用宿主机内网 IP:

bash
hostname -I | awk '{print $1}'
# 假设结果为 192.168.1.100,后续命令中替换

7.4 启动容器

bash
docker stop yudao-server 2>/dev/null; docker rm yudao-server 2>/dev/null

docker run -d \
  --name yudao-server \
  --restart always \
  -p 48080:48080 \
  -e "SPRING_PROFILES_ACTIVE=prod" \
  -e "JAVA_OPTS=-Xms512m -Xmx2048m -Djava.security.egd=file:/dev/./urandom" \
  -e "TZ=Asia/Shanghai" \
  -e "MYSQL_URL=jdbc:mysql://192.168.1.100:3306/ruoyi-office?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true" \
  -e "MYSQL_USERNAME=root" \
  -e "MYSQL_PASSWORD=YourPassword123!" \
  -e "REDIS_HOST=192.168.1.100" \
  -e "REDIS_PORT=6379" \
  -e "REDIS_PASSWORD=" \
  -v /data/app/logs:/yudao-server/logs \
  yudao-server:latest

192.168.1.100 替换为你的宿主机实际内网 IP。

💡 简化方案:使用 --network host 模式,容器直接使用宿主机网络,此时可用 127.0.0.1

bash
docker run -d \
  --name yudao-server \
  --restart always \
  --network host \
  -e "SPRING_PROFILES_ACTIVE=prod" \
  -e "JAVA_OPTS=-Xms512m -Xmx2048m" \
  -e "MYSQL_PASSWORD=YourPassword123!" \
  -e "REDIS_PASSWORD=" \
  -v /data/app/logs:/yudao-server/logs \
  yudao-server:latest

7.5 验证

bash
docker ps | grep yudao-server
docker logs -f yudao-server --tail 100

# 等待 30-60 秒
curl http://127.0.0.1:48080/actuator/health
# 返回 {"status":"UP"} 即成功

八、部署前端(Nginx)

8.1 确认文件

bash
mkdir -p /data/nginx/{conf/conf.d,logs}
# 前端文件已在 2.5 步上传到 /data/nginx/html/web/
ls -la /data/nginx/html/web/index.html

8.2 创建 Nginx 配置

bash
cat > /data/nginx/conf/conf.d/ruoyi-office.conf << 'NGINXEOF'
server {
    listen 80;
    server_name _;

    charset utf-8;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript
               application/json application/javascript application/xml+rss
               application/x-javascript image/svg+xml;

    # ========== 前端静态文件 ==========
    location /web {
        alias /usr/share/nginx/html/web;
        index index.html;
        try_files $uri $uri/ /web/index.html;
    }

    # 静态资源长缓存
    location ~* ^/web/(.+)\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
        root /usr/share/nginx/html;
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # ========== 后端 API 反向代理 ==========
    location /admin-api {
        proxy_pass http://宿主机IP: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;

        # WebSocket 支持
        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;
    }
}
NGINXEOF

⚠️ 务必替换 proxy_pass 中的 宿主机IP 为实际内网 IP(如 192.168.1.100)。Nginx 容器内 127.0.0.1 指向的是 Nginx 容器自身,无法访问后端容器。

💡 如果后端使用了 --network host,Nginx 也可以使用 --network host,此时 proxy_pass 可直接写 http://127.0.0.1:48080/admin-api

8.3 启动 Nginx 容器

bash
docker run -d \
  --name nginx \
  --restart always \
  -p 80:80 \
  -v /data/nginx/conf/conf.d:/etc/nginx/conf.d \
  -v /data/nginx/html:/usr/share/nginx/html \
  -v /data/nginx/logs:/var/log/nginx \
  nginx:latest

8.4 验证

bash
docker exec nginx nginx -t

curl -I http://127.0.0.1/web
# 返回 200 OK

浏览器访问 http://服务器IP/web,出现登录页即成功。

账号密码
adminadmin123

九、Docker Compose 一键部署(可选)

项目提供了 yudao-server/docker-compose.yml,可一键编排 MySQL + Redis + 后端。结合手动部署 Nginx,实现全容器化:

bash
cd /data/app/yudao-server

# 确保已构建镜像
docker build -t yudao-server:latest .

# 确保目录和配置已创建(参考第四、五章)

# 一键启动
docker compose up -d

# 查看状态
docker compose ps
docker compose logs -f yudao-server

十、日常更新

更新流程同样遵循「本地构建 → 上传产物 → 服务器重部署」的原则。

更新后端

bash
# ===== 本地/构建机 =====
cd ~/workspace/ruoyi-office && git pull origin master
mvn clean package -Dmaven.test.skip=true -Dskip.repackage=true -pl yudao-server -am -Pprod
scp yudao-server/target/yudao-server.jar root@服务器IP:/data/app/yudao-server/target/

# ===== 生产服务器 =====
cd /data/app/yudao-server
docker build -t yudao-server:latest .
docker stop yudao-server && docker rm yudao-server
# 重新执行 docker run 命令(同第七章)

更新前端

bash
# ===== 本地/构建机 =====
cd ~/workspace/ruoyi-office-vben && git pull origin master
pnpm install
pnpm -r --filter "./packages/**" --filter "./internal/**" build
cd apps/web-antd && pnpm build

# 上传(先清理再上传)
ssh root@服务器IP "rm -rf /data/nginx/html/web/*"
scp -r dist/* root@服务器IP:/data/nginx/html/web/
# 静态文件替换即时生效,无需重启 Nginx

更新数据库

bash
# 将增量 SQL 上传到服务器后执行
docker exec -i mysql mysql -uroot -p'YourPassword123!' ruoyi-office < 增量SQL文件.sql

十一、容器管理速查

bash
# ==================== 查看所有容器状态 ====================
docker ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# ==================== 后端 ====================
docker stop yudao-server
docker start yudao-server
docker restart yudao-server
docker logs -f yudao-server --tail 200

# ==================== Nginx ====================
docker exec nginx nginx -t           # 检查配置
docker exec nginx nginx -s reload    # 重载配置
docker restart nginx

# ==================== MySQL ====================
docker exec -it mysql mysql -uroot -p   # 进入 MySQL
docker restart mysql

# ==================== Redis ====================
docker exec -it redis redis-cli          # 进入 Redis CLI
docker restart redis

# ==================== 日志 ====================
docker logs -f yudao-server --tail 200               # 后端日志
docker exec nginx tail -f /var/log/nginx/error.log   # Nginx 错误日志
tail -f /data/app/logs/*.log                         # 挂载的后端日志

# ==================== 清理 ====================
docker image prune -f          # 清理无用镜像
docker system df               # 查看 Docker 磁盘占用

十二、常见问题

Q1:后端容器启动后立即退出?

bash
docker logs yudao-server --tail 200

常见原因:①数据库连接失败(检查 IP、端口、密码)②Redis 连接失败 ③内存不足(减小 -Xmx)④端口冲突。

Q2:容器内后端无法连接 MySQL / Redis?

容器内 127.0.0.1 指向容器自身,不是宿主机。三种解决方案:

bash
# 方案一:使用宿主机内网 IP(推荐)
-e "REDIS_HOST=192.168.1.100"

# 方案二:使用 --network host(容器共享宿主机网络)
docker run --network host ...

# 方案三:所有容器放同一 Docker 网络,用容器名互访
docker network create ruoyi-net
docker run --network ruoyi-net --name mysql ...
docker run --network ruoyi-net -e "REDIS_HOST=redis" ...

Q3:Nginx 反代后端接口报 502?

检查 ruoyi-office.confproxy_pass 的 IP 是否正确。Nginx 容器内的 127.0.0.1 无法访问后端容器。

Q4:Docker 镜像拉取慢或失败?

确认镜像加速已配置(参考 3.4 节),或手动指定国内源:

bash
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

Q5:前端构建报 JavaScript heap out of memory?

bash
export NODE_OPTIONS="--max-old-space-size=4096"
pnpm build

Q6:JAR 包超过 500MB?

构建命令必须包含 -Dskip.repackage=true,否则子模块各自打 Fat JAR 造成重复。

Q7:如何修改后端配置而不重新构建镜像?

通过 -e 环境变量覆盖即可,配置文件支持环境变量占位符:

bash
docker run ... \
  -e "MYSQL_PASSWORD=新密码" \
  -e "REDIS_HOST=新地址" \
  yudao-server:latest

Q8:如何备份数据?

bash
# MySQL
docker exec mysql mysqldump -uroot -p'YourPassword123!' ruoyi-office > backup_$(date +%Y%m%d).sql

# Redis
docker exec redis redis-cli BGSAVE

# 前端
tar -czf web-backup-$(date +%Y%m%d).tar.gz /data/nginx/html/web/