修改项目根目录的 pom.xml 追加 Maven 多环境配置
<profiles>
<profile>
<id>druid</id>
<properties>
<!-- 这里增加了 spring.active 属性 -->
<spring.active>druid</spring.active>
</properties>
<!-- 设置默认激活的配置 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.active>prod</spring.active>
</properties>
</profile>
</profiles>
<build>
<!-- 在 build 元素中追加资源管理相关配置 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>修改 ruoyi-admin/src/main/resources/application.yml 配置
spring:
profiles:
# 主要修改让 Spring Boot 能够读取到 Maven 的多环境配置
active: @spring.active@新建 ruoyi-admin/src/main/resources/application-prod.yml 生产环境配置
spring:
data:
redis:
host: ${REDIS_HOST}
port: ${REDIS_PORT}
database: 0
password: ${REDIS_PASSWORD}
timeout: 10s
lettuce:
pool:
min-idle: 0
max-idle: 8
max-active: 8
max-wait: -1ms
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
druid:
master:
url: jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_DATABASE}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: ${MYSQL_USERNAME}
password: ${MYSQL_PASSWORD}
slave:
enabled: false
url:
username:
password:
initialSize: 5
minIdle: 10
maxActive: 20
maxWait: 60000
connectTimeout: 30000
socketTimeout: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
maxEvictableIdleTimeMillis: 900000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
allow:
url-pattern: /druid/*
login-username: ruoyi
login-password: 123456
filter:
stat:
enabled: true
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true记住上面的变量,后面要用
${REDIS_HOST}
${REDIS_PORT}
${REDIS_PASSWORD}
${MYSQL_HOST}
${MYSQL_PORT}
${MYSQL_DATABASE}
${MYSQL_USERNAME}
${MYSQL_PASSWORD}
使用 mvn clean package -Pdruid 命令测试本地环境是否正常
使用【命令提示符 cmd】进入 ruoyi-admin\target 目录
使用 java -jar .\ruoyi-admin.jar 测试是否能够正常运行,确保激活的环境是 druid
注意:
可以继续使用
mvn clean package -Pprod命令测试是否能够正确加载生产环境配置也可以等到上生产时再行测试

进入 ruoyi-ui 目录
使用 yarn build:prod 命令测试是否能够正常打包
打包成功后会多出一个 dist 目录

先将修改后的代码提交到 GitLab 服务器
进入我们的生产环境,这里是 Ubuntu Service 虚拟机,拉取代码
# 克隆代码
git clone ssh://git@192.168.203.134:2222/lusifer/myproject.git
# 拉取代码
cd ~/myproject/
git pull执行完拉取命令后,可以看到代码已更行

创建 Maven 配置文件 settings.xml
配置文件与项目目录平级,这里是 cd ~
<settings>
<servers>
<server>
<id>maven-public</id>
<username>admin</username>
<password>12345678</password>
</server>
<server>
<id>maven-release</id>
<username>admin</username>
<password>12345678</password>
</server>
<server>
<id>maven-snapshots</id>
<username>admin</username>
<password>12345678</password>
</server>
</servers>
<mirrors>
<mirror>
<!-- 注意这里的 ID 需要匹配上面 Server 元素的 ID,用于配置 Nexus 的账号密码 -->
<id>maven-public</id>
<url>http://192.168.203.132:8081/repository/maven-public/</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
</settings>我们使用 Docker Compose 进行构建,创建一个名为 docker-compose-maven.yml 的脚本
services:
maven-build:
# 这里是 JDK21
image: maven:3.9.15-eclipse-temurin-21
volumes:
# 映射项目目录
- ./myproject:/app
# 本地仓库目录
- ~/.m2:/root/.m2
# 映射刚才创建的配置文件
- ./settings.xml:/root/.m2/settings.xml
working_dir: /app
# 使用开发环境配置打包作为测试
# command: mvn clean package -DskipTests -Pdruid
# 实际使用生产环境配置打包
command: mvn clean package -DskipTests -Pprod
environment:
- MAVEN_OPTS=-Dmaven.repo.local=/root/.m2/repository先手动下载镜像 docker pull maven:3.9.15-eclipse-temurin-21
使用如下命令执行构建
docker-compose -f docker-compose-maven.yml up可以看到执行成功会从私服下载依赖并开始构建

Maven 在下载依赖失败(版本错误、网络不通、私服异常)时,会在本地仓库生成 .lastUpdated 后缀的文件
这个文件是失败标记,Maven 会认为该依赖永久不可用
即使你后续修复了版本、网络、私服配置,Maven 也不会自动重新下载依赖,会直接读取这个标记文件,导致构建持续失败
只有删除所有 .lastUpdated 文件,Maven 才会重新从你的 Nexus3 私服拉取依赖
解决方案 1:直接运行清理命令
find ~/.m2 -name "*.lastUpdated" -type f -delete解决方案 2:保存为脚本文件
创建脚本文件
touch maven-clean.sh
chmod +x maven-clean.sh编辑文件
#!/bin/bash
# 清理 Maven 本地仓库中所有 .lastUpdated 失败标记文件
echo "开始清理 ~/.m2 下的 .lastUpdated 文件..."
find ~/.m2 -name "*.lastUpdated" -type f -delete
echo "清理完成!"执行清理脚本
./maven-clean.sh构建成功后可能会报一个错误,其实没有影响,打包确实是成功了
Exception in thread Thread-4 (watch_events):
Traceback (most recent call last):
File "/usr/lib/python3.12/threading.py", line 1073, in _bootstrap_inner
self.run()
File "/usr/lib/python3.12/threading.py", line 1010, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3/dist-packages/compose/cli/log_printer.py", line 202, in watch_events
for event in event_stream:
File "/usr/lib/python3/dist-packages/compose/project.py", line 626, in yield_loop
yield build_container_event(event)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/compose/project.py", line 594, in build_container_event
container = Container.from_id(self.client, event['id'])
~~~~~^^^^^^
KeyError: 'id'
root_maven-build_1 exited with code 0这是因为我们用的是 Docker Compose V1 官方已弃用 Python 版的 docker-compose,新版是 Go 语言编写的 docker compose
我们可以升级 Docker Compose 的版本到 V2
apt update && apt install -y docker-compose-v2之后执行就不要带横杠 (-) 了
# --remove-orphans 自动清理孤儿容器
docker compose -f docker-compose-maven.yml up --remove-orphans使用新版本打包就不再报错了

先手动下载镜像:docker pull node:22-alpine
我们使用 Docker Compose 进行构建,创建一个名为 docker-compose-node.yml 的脚本
services:
frontend-build:
image: node:22-alpine
environment:
- YARN_REGISTRY=https://registry.npmmirror.com
- SASS_BINARY_SITE=https://npmmirror.com/mirrors/node-sass/
volumes:
- ./myproject/ruoyi-ui:/app
- yarn-cache:/usr/local/share/.cache/yarn
working_dir: /app
command: sh -c "yarn && yarn build:prod"
volumes:
yarn-cache:使用如下命令执行构建
# --remove-orphans 自动清理孤儿容器
docker compose -f docker-compose-node.yml up --remove-orphans执行成功效果如下

进入前端代码目录,查看是否生成了 dist 目录

在 usr/local/docker 目录下创建 myproject 目录用于测试
创建 docker-compose.yml
services:
myproject:
# JDK 21
image: eclipse-temurin:21-jre-alpine
container_name: myproject
ports:
- "8080:8080"
volumes:
- ./app.jar:/app/app.jar
# 工作目录
working_dir: /app
# 启动命令:直接运行 jar
command: ["java", "-jar", "app.jar"]
# 环境变量(生产配置)
environment:
- TZ=Asia/Shanghai
- REDIS_HOST=192.168.203.129
- REDIS_PORT=6379
- REDIS_PASSWORD=123456
- MYSQL_HOST=192.168.203.129
- MYSQL_PORT=3306
- MYSQL_DATABASE=ry-vue
- MYSQL_USERNAME=root
- MYSQL_PASSWORD=123456
# 自动重启
restart: always复制刚才打包的 jar 文件到当前目录
cp ~/myproject/ruoyi-admin/target/ruoyi-admin.jar app.jar
启动脚本测试是否可以运行
docker compose up -d查看日志
docker compose logs -f注意现在的环境为生产环境,之前设置的变量(如 ${MYSQL_USERNAME})生效了

打开浏览器访问:http://你的服务器 IP:8080/
测试成功后先停止,我们一会开始处理前端
docker compose down继续在当前目录创建 nginx.conf 配置文件
注意:
下面配置中带有 IP 的部分修改为你自己的
由于项目的
.env.production配置文件中定义接口/prod-apinginxlocaltion部分修改为location /prod-api/
# 使用 nginx 用户,工作进程数自动适配 CPU 核心
user nginx;
worker_processes auto;
# 错误日志配置
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
# 单个工作进程最大连接数
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 访问日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
# 开启高效文件传输
sendfile on;
# 长连接超时时间
keepalive_timeout 65;
# 开启 gzip 压缩,优化前端资源加载速度
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 2;
gzip_types text/plain application/javascript text/css application/xml image/jpeg image/png;
gzip_vary on;
server {
# 监听 80 端口
listen 80;
server_name localhost;
# 前后端分离 - API 反向代理(解决跨域)
# 结尾带 / 会删除 api 前缀
location /prod-api/ {
proxy_pass http://192.168.203.129:8080/; # 结尾带斜杠会删除 api 前缀
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 根路径匹配
location / {
# 指向 Webpack 打包的 dist 目录(推荐 root,适配前端静态资源)
root /usr/share/nginx/html/;
index index.html;
# HTML 文件不缓存,保证实时更新
if ($request_filename ~* .*\.(html|htm)$) {
expires -1s;
add_header Cache-Control "no-cache";
}
}
# 错误页面配置
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}修改 docker-compose.yml 脚本,追加 nginx 相关配置,下面是完整脚本
services:
myproject:
# JDK 21
image: eclipse-temurin:21-jre-alpine
container_name: myproject
ports:
- "8080:8080"
volumes:
- ./app.jar:/app/app.jar
# 工作目录
working_dir: /app
# 启动命令:直接运行 jar
command: ["java", "-jar", "app.jar"]
# 环境变量(生产配置)
environment:
- TZ=Asia/Shanghai
- REDIS_HOST=192.168.203.129
- REDIS_PORT=6379
- REDIS_PASSWORD=123456
- MYSQL_HOST=192.168.203.129
- MYSQL_PORT=3306
- MYSQL_DATABASE=ry-vue
- MYSQL_USERNAME=root
- MYSQL_PASSWORD=123456
# 自动重启
restart: always
myproject-nginx:
image: nginx:1.26.2-alpine
restart: always
container_name: myproject-nginx
environment:
NGINX_HOST: localhost
NGINX_PORT: 80
ports:
- 80:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./dist:/usr/share/nginx/html手动拉取 nginx 镜像
docker pull nginx:1.26.2-alpine复制刚才构建的前端静态资源文件到当前目录
# 先删除当前目录下的 dist 目录,再把最新的复制过来
rm -rf ./dist && cp -r ~/myproject/ruoyi-ui/dist/ ./再次启动脚本并查看日志
# 启动容器
docker compose up -d
# 查看日志
docker compose logs -f现在可以直接访问了,试试看:http://192.168.203.129/
至此最基本的手动部署暂时告一段落