使用 Docker Compose 部署若依前后端分离项目 - [1] 前端部署记录(AI轻微润色版)
最后说说我对 AI 辅助开发的看法:AI 确实能提升效率,也能稍微拓宽我们的技能边界——好比原本技能范围是 600 码,现在能扩展到 660 码左右。你无法给 AI 提供有效的调试提示,AI 能帮你的也就有限了。用 AI 辅助开发经常遇到这种情况:它给出的答案往往不完整,如果你不提,它也不会主动提醒你可能遇到的问题。这是因为 Vue 是单页应用,很多路由在服务器上并没有对应的文件,所以需要把所有的
最近我在学习前端 Vue 技术,找了一个前后端分离的项目资料来练手。之前一直用 Docker 管理数据库和 Redis,也了解过后台服务的 Docker 部署,但还没真正用 Docker 部署过前端项目。正好心血来潮,就想把前端也容器化。这样一来,前端、后端、数据库和 Redis 就都能用 Docker 统一管理了,岂不是可以实现“一键上线”?说干就干。
项目需要同时支持本地运行和容器运行,所以我立刻意识到需要配置多环境。既然 Spring 有多环境配置,Vue 没道理没有。查资料、问 AI,一番操作之后,我配置了这两个环境文件:
./RuoYi-Vue3/.env.development
./RuoYi-Vue3/.env.production
这里得吐槽一下环境配置的使用方式。在 package.json
里,脚本原来是这样的:
"scripts": {
"dev": "vite --mode development",
"build": "vite build --mode production",
"preview": "vite preview"
}
但其实默认情况下,运行 dev
就会自动使用 .env.development
,而 build
则会用 .env.production
。这种“约定优于配置”看起来省事,但其实容易藏坑——如果你不知道这个约定,很可能配置了半天却发现根本没生效。写配置明明就一次的事,真没必要为了省这点事增加未来的调试成本。(每次遇到这种“约定”带来的坑,我都忍不住要吐槽几句)
若依项目本身是自带这两个环境文件的,不过内容并不完全适合容器运行。我做了一点调整,主要是增加了一个环境变量用来区分后台服务的地址,这样在 Docker 网络里就可以直接用服务名访问后端了:
# 容器环境,ruoyi-backend 是后台服务的容器名
VITE_API_BASE_URL = http://ruoyi-backend:8080
# 本地环境
VITE_API_BASE_URL = http://localhost:8080
原本的项目里已经配置了代理,我顺着这个思路,在 vite.config.js
里把后端地址改成读取环境变量的方式。查了一下怎么在 Vite 配置中读取环境变量,边试边改,总算搞明白了。
一开始我看到有资料说可以这样读取:
const VITE_API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
在 request.js
里确实可以,但在 vite.config.js
里却行不通。后来我才理解,虽然都是 JS 文件,但 vite.config.js
是给构建工具用的,运行环境不同,不能直接使用 import.meta.env
。正确的方式是使用 Vite 提供的 loadEnv
:
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ command, mode }) => {
// 根据当前环境加载对应的 .env 文件
const env = loadEnv(mode, process.cwd(), '')
})
搞定了多环境配置,接下来就是写 Dockerfile 了。不用说,继续请 AI 帮忙:
# 第一阶段:使用 Node 镜像打包
FROM node:20-alpine3.19 AS frontend-builder
WORKDIR /build-app
COPY . .
RUN npm install
RUN npm run build:prod
# 第二阶段:使用 Nginx 镜像部署
FROM nginx:1.29.1-alpine3.22-otel
EXPOSE 80
WORKDIR /app
# 替换 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 将第一阶段的静态文件复制到 nginx 中
RUN rm -rf /usr/share/nginx/html
RUN mkdir /usr/share/nginx/html
COPY --from=frontend-builder /build-app/dist /usr/share/nginx/html
# 运行 nginx
CMD ["nginx", "-g", "daemon off;"]
这个 Dockerfile 的结构很清晰:先用 Node 镜像构建出静态文件,再把这些文件复制到 Nginx 镜像中。令我惊喜的是,这个配置没有任何硬编码的应用相关信息,非常通用!
不过还缺一个 Nginx 的配置文件,于是第二个坑来了。最初的配置是这样的:
server {
listen 80;
listen [::]:80;
server_name localhost;
access_log /var/log/nginx/host.access.log main;
# 前端静态资源
location / {
root /usr/share/nginx/html;
index index.html index.htm;
# 新增下面这句,其他是 nginx 默认配置
# 解决部分前端框架的路由问题,在浏览器刷新时报 404
try_files $uri $uri/ /index.html;
}
# 新增:反向代理 API 请求
# 所有以 /api 开头的请求,转发到后端服务
location /prod-api/ {
# 注意:http://ruoyi-backend:8080 是 Docker 内部服务名 + 端口
proxy_pass http://ruoyi-backend:8080/;
# 以下配置确保后端能正确识别客户端信息
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_buffering off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
这个配置也是 AI 生成的,但一开始并不能直接用,调试了好久。其中最关键的是这一行:
try_files $uri $uri/ /index.html;
这是因为 Vue 是单页应用,很多路由在服务器上并没有对应的文件,所以需要把所有的路由请求都重定向到 index.html。
另一个大坑是:我发现容器部署后始终连不上后台。排查了很久才明白,Vue 开发时配置的代理服务器(用来解决跨域问题)在打包后根本不会生效!所以之前配置的环境变量什么的都没用,必须在 Nginx 里配置反向代理:
proxy_pass http://ruoyi-backend:8080/;
用 AI 辅助开发经常遇到这种情况:它给出的答案往往不完整,如果你不提,它也不会主动提醒你可能遇到的问题。但一旦你给出了正确的提示,它又能提供很大帮助。
回顾一下,前端调整主要涉及这五个文件,至此基本说清楚了。部署过程中还遇到了其他问题,下一篇再继续记录。
最后说说我对 AI 辅助开发的看法:AI 确实能提升效率,也能稍微拓宽我们的技能边界——好比原本技能范围是 600 码,现在能扩展到 660 码左右。但如果你完全依赖 AI 而不懂基本原理,很容易陷入“不对,不对,还是不对……”的死循环。你无法给 AI 提供有效的调试提示,AI 能帮你的也就有限了。
更多推荐
所有评论(0)