RuoYi-Vue Docker Compose 部署完整指南
基于实际部署过程整理,包含所有踩坑记录和解决方案
项目信息:RuoYi-Vue 3.9.2 | Spring Boot 4.0.3 | JDK 17 | Vue 3 + Vite
服务器:阿里云 Ubuntu | IP: 121.43.53.142
📋 部署流程总览
第1步:服务器安装 Docker 和 Docker Compose
第2步:配置 Docker 国内镜像加速
第3步:本地修改后端 Docker 配置文件
第4步:本地打包后端项目
第5步:本地构建前端项目
第6步:服务器创建部署目录结构
第7步:上传所有文件到服务器
第8步:放行防火墙端口
第9步:启动 Docker Compose
第10步:验证访问
架构说明
Docker Compose 容器编排
┌──────────────────────────────────────────────────────┐
│ Docker Compose 编排 (ruoyi-net 网络) │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ ruoyi-nginx │ │ruoyi-backend│ │
│ │ :81→80 │ │ :8081→8080 │ │
│ │ (前端入口) │──│ (后端API) │ │
│ └─────────────┘ └──────┬──────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ │
│ │ ruoyi-mysql │ │ ruoyi-redis │ │
│ │ :3307→3306 │ │ :6380→6379 │ │
│ │ (数据库) │ │ (缓存) │ │
│ └─────────────┘ └─────────────┘ │
└──────────────────────────────────────────────────────┘
端口规划(与宝塔部署错开,两套可同时运行)
| 服务 | 宝塔部署端口 | Docker部署端口 | 说明 |
|---|---|---|---|
| Nginx | 80 | 81 | 前端入口 |
| Backend | 8080 | 8081 | 后端API |
| MySQL | 3306 | 3307 | 数据库 |
| Redis | 6379 | 6380 | 缓存 |
文件结构
项目根目录/
├── docker-compose-v2.yml ← Docker Compose 编排文件
├── sql/
│ ├── ry_20260321.sql ← 建表SQL
│ └── quartz.sql ← 定时任务SQL
├── docker/
│ ├── backend/
│ │ └── Dockerfile ← 后端镜像构建
│ ├── nginx/
│ │ ├── Dockerfile ← 前端镜像构建
│ │ └── default.conf ← Nginx配置
│ ├── mysql/data/ ← MySQL数据持久化(自动生成)
│ ├── redis/data/ ← Redis数据持久化(自动生成)
│ └── uploadPath/ ← 文件上传目录
└── ruoyi-admin/src/main/resources/
└── application-docker.yml ← Docker专用Spring配置
第1步:服务器安装 Docker 和 Docker Compose
安装 Docker
bash
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
启动 Docker 并设置开机自启
bash
systemctl start docker
systemctl enable docker
验证安装
bash
docker --version
# 应输出:Docker version 2x.x.x
docker compose version
# 应输出:Docker Compose version v2.x.x
Docker 20.10+ 自带 compose 插件,无需单独安装 docker-compose
第2步:配置 Docker 国内镜像加速
⚠️ 坑1:Docker Hub 拉取镜像超时
错误现象:
Error response from daemon: Get "https://registry-1.docker.io/v2/":
context deadline exceeded (Client.Timeout exceeded while awaiting headers)
原因: 国内服务器访问 Docker Hub(registry-1.docker.io)极慢或无法访问
解决方案: 配置国内镜像加速源
bash
mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me",
"https://docker.rainbond.cc"
]
}
EOF
systemctl daemon-reload
systemctl restart docker
验证镜像加速配置
bash
docker info | grep -A 5 "Registry Mirrors"
期望输出:
Registry Mirrors:
https://docker.1ms.run/
https://docker.xuanyuan.me/
https://docker.rainbond.cc/
第3步:本地修改后端 Docker 配置文件
3.1 创建 application-docker.yml
文件位置: ruoyi-admin/src/main/resources/application-docker.yml
yaml
spring:
datasource:
druid:
master:
url: jdbc:mysql://ruoyi-mysql:3306/ruoyi_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
username: ruoyi_db
password: Ruoyi@2026!Prod
data:
redis:
host: ruoyi-redis
port: 6379
password: '@@root123456'
关键说明:
| 配置项 | 值 | 说明 |
|---|---|---|
master.url 中的主机名 |
ruoyi-mysql |
Docker 网络内的容器名,不是 localhost |
redis.host |
ruoyi-redis |
Docker 网络内的容器名,不是 localhost |
allowPublicKeyRetrieval=true |
必须加 | MySQL 8.0 认证需要(见坑3) |
| Redis 密码加引号 | '@@root123456' |
YAML 特殊字符必须加引号(见坑2) |
3.2 创建后端 Dockerfile
文件位置: docker/backend/Dockerfile
dockerfile
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY ruoyi-admin.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Xms256m", "-Xmx512m", "-jar", "app.jar", "--spring.profiles.active=druid,docker"]
关键说明:
| 配置项 | 值 | 说明 |
|---|---|---|
| 基础镜像 | eclipse-temurin:17-jre-alpine |
JDK 17 JRE,Alpine 版本体积小(约170MB) |
--spring.profiles.active |
druid,docker |
先加载 druid 再加载 docker(见坑4) |
| JVM 内存 | -Xms256m -Xmx512m |
根据服务器内存调整 |
3.3 创建前端 Dockerfile
文件位置: docker/nginx/Dockerfile
dockerfile
FROM nginx:alpine
COPY default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
EXPOSE 80
3.4 创建 Nginx 配置文件
文件位置: docker/nginx/default.conf
nginx
server {
listen 80;
server_name _;
index index.html;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html;
}
location /prod-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://ruoyi-backend:8080/;
}
location /profile/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://ruoyi-backend:8080/profile/;
}
client_max_body_size 50m;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
关键说明:
| 配置项 | 值 | 说明 |
|---|---|---|
proxy_pass 主机名 |
ruoyi-backend |
Docker 网络内的容器名,不是 localhost |
server_name |
_ |
Docker 内部 Nginx 不存在冲突问题 |
3.5 创建 docker-compose-v2.yml
文件位置: 项目根目录 docker-compose-v2.yml
yaml
version: "3.8"
services:
ruoyi-mysql:
image: mysql:8.0
container_name: ruoyi-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: RuoyiRoot@2026!
MYSQL_DATABASE: ruoyi_db
MYSQL_USER: ruoyi_db
MYSQL_PASSWORD: Ruoyi@2026!Prod
TZ: Asia/Shanghai
ports:
- "3307:3306"
volumes:
- ./docker/mysql/data:/var/lib/mysql
- ./sql/ry_20260321.sql:/docker-entrypoint-initdb.d/1_ry_20260321.sql
- ./sql/quartz.sql:/docker-entrypoint-initdb.d/2_quartz.sql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --skip-character-set-client-handshake --default-authentication-plugin=mysql_native_password
networks:
- ruoyi-net
ruoyi-redis:
image: redis:7.0-alpine
container_name: ruoyi-redis
restart: always
command: redis-server --requirepass '@@root123456'
ports:
- "6380:6379"
volumes:
- ./docker/redis/data:/data
networks:
- ruoyi-net
ruoyi-backend:
build:
context: ./docker/backend
dockerfile: Dockerfile
container_name: ruoyi-backend
restart: always
ports:
- "8081:8080"
volumes:
- ./docker/uploadPath:/www/wwwroot/ruoyi/uploadPath
depends_on:
- ruoyi-mysql
- ruoyi-redis
networks:
- ruoyi-net
ruoyi-nginx:
build:
context: ./docker/nginx
dockerfile: Dockerfile
container_name: ruoyi-nginx
restart: always
ports:
- "81:80"
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- ruoyi-backend
networks:
- ruoyi-net
networks:
ruoyi-net:
driver: bridge
关键配置说明:
| 配置项 | 说明 |
|---|---|
restart: always |
容器崩溃或服务器重启后自动重启 |
ports: "3307:3306" |
宿主机3307映射到容器3306,避免与宝塔MySQL冲突 |
ports: "6380:6379" |
宿主机6380映射到容器6379,避免与宝塔Redis冲突 |
ports: "8081:8080" |
宿主机8081映射到容器8080,避免与宝塔后端冲突 |
ports: "81:80" |
宿主机81映射到容器80,避免与宝塔Nginx冲突 |
docker-entrypoint-initdb.d |
MySQL首次启动时自动执行SQL脚本初始化数据库 |
SQL文件编号 1_ 2_ |
确保按顺序执行(先建表再建定时任务) |
ruoyi-net 网络 |
所有容器在同一网络,可通过容器名互相访问 |
第4步:本地打包后端项目
powershell
cd D:\java_space\RuoYi_java\RuoYi-Vue
# 确保 JDK 17
$env:JAVA_HOME="C:\Program Files\Java\jdk-17"
$env:Path="C:\Program Files\Java\jdk-17\bin;$env:Path"
# 打包
mvn clean package -DskipTests
打包成功后 JAR 文件位置:
ruoyi-admin/target/ruoyi-admin.jar(约 85MB)
第5步:本地构建前端项目
powershell
cd D:\java_space\Ruoyi_vue3\RuoYi-Vue3
# 安装依赖
pnpm install
# 构建生产环境包
pnpm build:prod
构建成功后 dist 目录位置:
D:\java_space\Ruoyi_vue3\RuoYi-Vue3\dist\
├── index.html
└── assets/
第6步:服务器创建部署目录结构
bash
mkdir -p /www/docker/ruoyi/docker/{backend,nginx/dist,mysql/data,redis/data,uploadPath}
mkdir -p /www/docker/ruoyi/sql
目录说明:
| 目录 | 用途 |
|---|---|
/www/docker/ruoyi/ |
部署根目录 |
docker/backend/ |
存放 Dockerfile 和 JAR 包 |
docker/nginx/ |
存放 Dockerfile、Nginx 配置和前端 dist |
docker/nginx/dist/ |
前端静态文件 |
docker/mysql/data/ |
MySQL 数据持久化(容器重启数据不丢失) |
docker/redis/data/ |
Redis 数据持久化 |
docker/uploadPath/ |
文件上传目录 |
sql/ |
SQL 初始化脚本 |
验证目录结构:
bash
tree /www/docker/ruoyi/ -L 3
第7步:上传所有文件到服务器
上传清单
| 本地文件 | 上传到服务器路径 |
|---|---|
docker-compose-v2.yml |
/www/docker/ruoyi/docker-compose-v2.yml |
docker/backend/Dockerfile |
/www/docker/ruoyi/docker/backend/Dockerfile |
ruoyi-admin/target/ruoyi-admin.jar |
/www/docker/ruoyi/docker/backend/ruoyi-admin.jar |
docker/nginx/Dockerfile |
/www/docker/ruoyi/docker/nginx/Dockerfile |
docker/nginx/default.conf |
/www/docker/ruoyi/docker/nginx/default.conf |
Ruoyi_vue3/RuoYi-Vue3/dist/* |
/www/docker/ruoyi/docker/nginx/dist/ |
sql/ry_20260321.sql |
/www/docker/ruoyi/sql/ry_20260321.sql |
sql/quartz.sql |
/www/docker/ruoyi/sql/quartz.sql |
SCP 命令上传(推荐)
powershell
# 编排文件
scp D:\java_space\RuoYi_java\RuoYi-Vue\docker-compose-v2.yml root@121.43.53.142:/www/docker/ruoyi/
# 后端 Dockerfile
scp D:\java_space\RuoYi_java\RuoYi-Vue\docker\backend\Dockerfile root@121.43.53.142:/www/docker/ruoyi/docker/backend/
# 后端 JAR 包(较大,耐心等待)
scp D:\java_space\RuoYi_java\RuoYi-Vue\ruoyi-admin\target\ruoyi-admin.jar root@121.43.53.142:/www/docker/ruoyi/docker/backend/
# 前端 Dockerfile
scp D:\java_space\RuoYi_java\RuoYi-Vue\docker\nginx\Dockerfile root@121.43.53.142:/www/docker/ruoyi/docker/nginx/
# Nginx 配置
scp D:\java_space\RuoYi_java\RuoYi-Vue\docker\nginx\default.conf root@121.43.53.142:/www/docker/ruoyi/docker/nginx/
# 前端 dist 目录
scp -r D:\java_space\Ruoyi_vue3\RuoYi-Vue3\dist\* root@121.43.53.142:/www/docker/ruoyi/docker/nginx/dist/
# SQL 脚本
scp D:\java_space\RuoYi_java\RuoYi-Vue\sql\ry_20260321.sql root@121.43.53.142:/www/docker/ruoyi/sql/
scp D:\java_space\RuoYi_java\RuoYi-Vue\sql\quartz.sql root@121.43.53.142:/www/docker/ruoyi/sql/
宝塔面板上传(小文件推荐)
宝塔面板 → 文件 → 导航到目标目录 → 上传按钮 → 选择文件 → 等待完成
⚠️ 上传 dist 时,上传 dist 里面的内容(index.html、assets/),不是 dist 文件夹本身
验证上传结果
bash
tree /www/docker/ruoyi/ -L 3
第8步:放行防火墙端口
宝塔面板放行
宝塔面板 → 安全 → 防火墙 → 添加规则
端口:81,备注:Docker-RuoYi-Nginx
阿里云安全组放行
阿里云控制台 → ECS → 安全组 → 入方向规则 → 添加
协议:TCP,端口:81,授权对象:0.0.0.0/0
⚠️ 只需放行 81 端口!8081、3307、6380 不需要对外放行,外部通过 Nginx 代理即可访问
第9步:启动 Docker Compose
构建并启动
bash
cd /www/docker/ruoyi
docker compose -f docker-compose-v2.yml up -d --build
首次启动过程
1. 拉取 MySQL 8.0 镜像(约500MB,1-3分钟)
2. 拉取 Redis 7.0 Alpine 镜像(约30MB,几秒)
3. 拉取 JDK 17 JRE Alpine 镜像(约170MB,30秒)
4. 拉取 Nginx Alpine 镜像(约25MB,几秒)
5. MySQL 初始化数据库(执行SQL脚本,约30秒)
6. 后端启动连接数据库(约20秒,可能重启几次等MySQL就绪)
7. Nginx 启动(几秒)
查看容器状态
bash
docker compose -f docker-compose-v2.yml ps
期望输出(所有状态为 Up):
NAME IMAGE STATUS PORTS
ruoyi-mysql mysql:8.0 Up 0.0.0.0:3307->3306/tcp
ruoyi-redis redis:7.0-alpine Up 0.0.0.0:6380->6379/tcp
ruoyi-backend ruoyi-docker-backend Up 0.0.0.0:8081->8080/tcp
ruoyi-nginx ruoyi-docker-nginx Up 0.0.0.0:81->80/tcp
查看后端日志
bash
docker logs -f ruoyi-backend
看到以下内容表示启动成功:
Started RuoYiApplication in XX seconds
(♥◠‿◠)ノ゙ 若依启动成功 ლ(´ڡ`ლ)゙
⚠️ 首次启动时后端可能因为 MySQL 还在初始化而报错重启,这是正常的!
restart: always配置会让后端自动重试,等 MySQL 就绪后就会成功。
第10步:验证访问
浏览器访问
http://121.43.53.142:81
默认登录信息
账号:admin
密码:admin123
⚠️ 登录后立即修改默认密码!
功能验证清单
□ 登录成功
□ 菜单正常显示
□ 用户管理页面正常
□ 文件上传功能正常
□ 退出登录正常
两套部署对比
| 地址 | 部署方式 | 端口 |
|---|---|---|
http://121.43.53.142:80 |
宝塔部署 | 80 |
http://121.43.53.142:81 |
Docker 部署 | 81 |
两套部署使用不同的数据库和 Redis,数据完全独立,互不干扰!
🔧 常用 Docker 运维命令
容器管理
bash
cd /www/docker/ruoyi
# 查看所有容器状态
docker compose -f docker-compose-v2.yml ps
# 查看某个容器日志
docker logs -f ruoyi-backend
docker logs -f ruoyi-mysql
docker logs -f ruoyi-nginx
docker logs -f ruoyi-redis
# 重启某个服务
docker compose -f docker-compose-v2.yml restart ruoyi-backend
# 停止所有容器
docker compose -f docker-compose-v2.yml down
# 重新构建并启动(代码更新后)
docker compose -f docker-compose-v2.yml up -d --build
# 只重建后端
docker compose -f docker-compose-v2.yml up -d --build ruoyi-backend
# 只重建前端
docker compose -f docker-compose-v2.yml up -d --build ruoyi-nginx
进入容器内部排查
bash
# 进入后端容器
docker exec -it ruoyi-backend sh
# 进入 MySQL 容器
docker exec -it ruoyi-mysql bash
# 进入 Redis 容器
docker exec -it ruoyi-redis sh
# 在 MySQL 容器内连接数据库
mysql -u ruoyi_db -p'Ruoyi@2026!Prod' ruoyi_db
代码更新后重新部署
bash
# 1. 本地重新打包 JAR
mvn clean package -DskipTests
# 2. 上传新 JAR
scp ruoyi-admin/target/ruoyi-admin.jar root@121.43.53.142:/www/docker/ruoyi/docker/backend/
# 3. 服务器重建后端容器
cd /www/docker/ruoyi
docker compose -f docker-compose-v2.yml up -d --build ruoyi-backend
前端更新后重新部署
bash
# 1. 本地重新构建
pnpm build:prod
# 2. 上传新 dist
scp -r dist/* root@121.43.53.142:/www/docker/ruoyi/docker/nginx/dist/
# 3. 服务器重建前端容器
cd /www/docker/ruoyi
docker compose -f docker-compose-v2.yml up -d --build ruoyi-nginx
⚠️ 踩坑总结
坑1:Docker Hub 拉取镜像超时
| 项目 | 内容 |
|---|---|
| 错误信息 | context deadline exceeded (Client.Timeout exceeded while awaiting headers) |
| 原因 | 国内服务器无法访问 Docker Hub(registry-1.docker.io) |
| 解决方案 | 配置 /etc/docker/daemon.json 添加国内镜像加速源 |
| 预防 | 部署前先配置好镜像加速 |
坑2:Redis 密码特殊字符导致 YAML 解析失败
| 项目 | 内容 |
|---|---|
| 错误信息 | found character '@' that cannot start any token |
| 原因 | Redis 密码 @@root123456 以 @ 开头,YAML 解析器无法识别 |
| 解决方案 | 用引号包裹密码:password: '@@root123456' |
| 预防 | 所有含特殊字符的 YAML 值都用引号包裹 |
坑3:MySQL 8.0 Public Key Retrieval 不允许
| 项目 | 内容 |
|---|---|
| 错误信息 | Public Key Retrieval is not allowed |
| 原因 | MySQL 8.0 默认使用 caching_sha2_password 认证,JDBC 首次连接需要获取公钥但默认不允许 |
| 解决方案 | JDBC URL 添加 allowPublicKeyRetrieval=true 参数 |
| 预防 | Docker 中 MySQL 8.0 连接始终加此参数 |
坑4:Spring Profile 加载顺序导致配置缺失
| 项目 | 内容 |
|---|---|
| 错误信息 | UnsatisfiedDependencyException: Error creating bean with name 'druidProperties' |
| 原因 | --spring.profiles.active=docker 只加载 docker profile,缺少 druid profile 中的连接池配置(connectTimeout、socketTimeout 等) |
| 解决方案 | 改为 --spring.profiles.active=druid,docker,先加载 druid 再加载 docker 覆盖 |
| 预防 | docker profile 只放需要覆盖的配置(数据库地址、Redis地址),其余从 druid 继承 |
坑5:SQL 初始化脚本执行顺序
| 项目 | 内容 |
|---|---|
| 错误信息 | quartz 表不存在(如果 quartz.sql 先执行) |
| 原因 | docker-entrypoint-initdb.d 按文件名排序执行,如果 quartz.sql 排在 ry 前面会报错 |
| 解决方案 | SQL 文件加编号前缀:1_ry_20260321.sql、2_quartz.sql |
| 预防 | 始终给初始化脚本加编号确保执行顺序 |
坑6:MySQL 数据已存在时 SQL 不再执行
| 项目 | 内容 |
|---|---|
| 现象 | 修改 SQL 后重新启动容器,修改未生效 |
| 原因 | docker-entrypoint-initdb.d 只在 MySQL 首次初始化时执行,数据目录已有数据则跳过 |
| 解决方案 | 如需重新初始化,删除数据目录:rm -rf /www/docker/ruoyi/docker/mysql/data/*,然后重启容器 |
| 预防 | 了解此机制,避免误删数据目录 |
坑7:中文乱码(菜单显示乱码)
| 项目 | 内容 |
|---|---|
| 现象 | 左侧菜单显示乱码,如 ç"¨æˆ·ç®¡ç† |
| 原因 | MySQL 字符集配置不完整,客户端连接时使用了 latin1 编码 |
| 解决方案 | MySQL command 加 --skip-character-set-client-handshake,JDBC URL 用 characterEncoding=UTF-8 |
| 预防 | 部署时确保 MySQL 和 JDBC 的字符集配置都正确 |
坑8:Java 不认识 utf8mb4
| 项目 | 内容 |
|---|---|
| 错误信息 | Unsupported character encoding 'utf8mb4' |
| 原因 | MySQL 的 utf8mb4 是 MySQL 特有的字符集名,Java/JDBC 只认识 UTF-8 |
| 解决方案 | JDBC URL 中用 characterEncoding=UTF-8(大写),MySQL 服务端用 utf8mb4,两者自动转换 |
| 预防 | 切记:Java 侧用 UTF-8,MySQL 侧用 utf8mb4,不要混用 |
📋 踩坑速查表
| 编号 | 坑 | 现象 | 解决方案 |
|---|---|---|---|
| 坑1 | Docker Hub 超时 | 镜像拉取失败 | 配置国内镜像加速源 |
| 坑2 | YAML 特殊字符 | 启动报错 found character '@' |
密码加引号 |
| 坑3 | MySQL 公钥检索 | Public Key Retrieval is not allowed |
JDBC URL 加 allowPublicKeyRetrieval=true |
| 坑4 | Profile 加载顺序 | druidProperties 注入失败 |
--spring.profiles.active=druid,docker |
| 坑5 | SQL 执行顺序 | quartz 表不存在 | SQL 文件加编号前缀 |
| 坑6 | SQL 不重复执行 | 修改 SQL 后未生效 | 删除 mysql/data 目录重新初始化 |
| 坑7 | 中文乱码 | 菜单显示乱码 | MySQL 加 --skip-character-set-client-handshake |
| 坑8 | utf8mb4 不识别 | Unsupported character encoding |
JDBC URL 用 UTF-8 而非 utf8mb4 |
🔒 安全加固(上线必做)
| 项目 | 当前值 | 必须改为 |
|---|---|---|
| MySQL root 密码 | RuoyiRoot@2026! | 更强的自定义密码 |
| MySQL 业务用户密码 | Ruoyi@2026!Prod | 更强的自定义密码 |
| Redis 密码 | @@root123456 | 更强的自定义密码 |
| JWT secret | aB3$xY7@mK9#pQ2&nW5*rT8!vJ4^fH6 | 随机长字符串 |
| 管理员密码 | admin123 | 强密码 |
| 宿主机端口暴露 | 3307/6380/8081 对外 | 安全组关闭这些端口,只留 81 |
🆚 宝塔部署 vs Docker 部署对比
| 对比项 | 宝塔部署 | Docker 部署 |
|---|---|---|
| 环境安装 | 手动安装 Nginx/MySQL/Redis/JDK | Docker 自动拉取镜像 |
| 配置复杂度 | 需要逐个配置每个服务 | docker-compose 一键编排 |
| 数据库初始化 | 手动导入 SQL | 自动执行初始化脚本 |
| 进程管理 | 进程守护管理器 | restart: always 自动重启 |
| 迁移到新服务器 | 需要重新安装所有环境 | 复制目录 + docker compose up |
| 多环境隔离 | 困难(端口冲突) | 容易(改端口映射即可) |
| 回滚 | 手动替换文件 | 重新构建镜像 |
| 学习成本 | 低(可视化面板) | 中(需了解 Docker 概念) |
| 适用场景 | 单项目、快速部署 | 多环境、CI/CD、团队协作 |
📌 完整配置文件参考
application-docker.yml
yaml
spring:
datasource:
druid:
master:
url: jdbc:mysql://ruoyi-mysql:3306/ruoyi_db?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
username: ruoyi_db
password: Ruoyi@2026!Prod
data:
redis:
host: ruoyi-redis
port: 6379
password: '@@root123456'
docker/backend/Dockerfile
dockerfile
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY ruoyi-admin.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-Xms256m", "-Xmx512m", "-jar", "app.jar", "--spring.profiles.active=druid,docker"]
docker/nginx/Dockerfile
dockerfile
FROM nginx:alpine
COPY default.conf /etc/nginx/conf.d/default.conf
COPY dist/ /usr/share/nginx/html/
EXPOSE 80
docker/nginx/default.conf
nginx
server {
listen 80;
server_name _;
index index.html;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html;
}
location /prod-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://ruoyi-backend:8080/;
}
location /profile/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://ruoyi-backend:8080/profile/;
}
client_max_body_size 50m;
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
docker-compose-v2.yml
yaml
version: "3.8"
services:
ruoyi-mysql:
image: mysql:8.0
container_name: ruoyi-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: RuoyiRoot@2026!
MYSQL_DATABASE: ruoyi_db
MYSQL_USER: ruoyi_db
MYSQL_PASSWORD: Ruoyi@2026!Prod
TZ: Asia/Shanghai
ports:
- "3307:3306"
volumes:
- ./docker/mysql/data:/var/lib/mysql
- ./sql/ry_20260321.sql:/docker-entrypoint-initdb.d/1_ry_20260321.sql
- ./sql/quartz.sql:/docker-entrypoint-initdb.d/2_quartz.sql
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci --skip-character-set-client-handshake --default-authentication-plugin=mysql_native_password
networks:
- ruoyi-net
ruoyi-redis:
image: redis:7.0-alpine
container_name: ruoyi-redis
restart: always
command: redis-server --requirepass '@@root123456'
ports:
- "6380:6379"
volumes:
- ./docker/redis/data:/data
networks:
- ruoyi-net
ruoyi-backend:
build:
context: ./docker/backend
dockerfile: Dockerfile
container_name: ruoyi-backend
restart: always
ports:
- "8081:8080"
volumes:
- ./docker/uploadPath:/www/wwwroot/ruoyi/uploadPath
depends_on:
- ruoyi-mysql
- ruoyi-redis
networks:
- ruoyi-net
ruoyi-nginx:
build:
context: ./docker/nginx
dockerfile: Dockerfile
container_name: ruoyi-nginx
restart: always
ports:
- "81:80"
volumes:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- ruoyi-backend
networks:
- ruoyi-net
networks:
ruoyi-net:
driver: bridge