在本地开发、内网测试或小型项目部署场景中,Vue3 + SpringBoot 是最主流的前后端分离技术栈之一。本文将手把手教你通过编写Dockerfile和docker-compose.yml文件,实现这套技术栈的一键部署,且仅暴露回环端口(127.0.0.1),保证服务仅本机可访问,兼顾便捷性与安全性。
一、场景与技术选型
核心需求
技术栈:前端 Vue3(Vite 构建) + 后端 SpringBoot 3.x;
部署方式:Docker 容器化,环境完全隔离;
网络安全:仅绑定回环地址,避免外网访问;
运维便捷:一键启动 / 停止,自动处理依赖和网络。
前置准备
服务器 / 本地环境已安装 Docker 和 Docker Compose;
已完成 Vue3 前端项目和 SpringBoot 后端项目开发;
基础的 Docker 命令认知(无需深入,本文全程复制即用)。
二、项目目录结构
先梳理标准化的项目结构,后续所有配置均基于此,建议按此目录组织代码:
vue3-springboot-demo/
├── frontend/ # Vue3前端项目(Vite构建)
│ ├── Dockerfile # 前端镜像构建文件
│ ├── package.json # 前端依赖
│ ├── vite.config.js # Vite配置
│ └── dist/ # 打包后的静态文件(npm run build生成)
├── backend/ # SpringBoot后端项目
│ ├── Dockerfile # 后端镜像构建文件
│ ├── pom.xml # Maven依赖
│ └── src/ # 后端源码
└── docker-compose.yml # Compose编排文件(核心)
三、编写 Dockerfile(前后端镜像构建)
1. 前端 Dockerfile(Vue3 + Vite)
路径:frontend/Dockerfile
# 阶段1:构建前端静态文件
FROM node:18-alpine as build-stage
WORKDIR /app
# 复制依赖文件(利用Docker缓存,避免每次都重装依赖)
COPY package*.json ./
# 国内镜像源加速安装
RUN npm install --registry=https://registry.npmmirror.com
# 复制全部源码
COPY . .
# 打包构建(Vite构建生产环境包)
RUN npm run build
# 阶段2:使用Nginx部署静态文件(轻量、高性能)
FROM nginx:alpine as production-stage
# 复制构建好的静态文件到Nginx默认目录
COPY --from=build-stage /app/dist /usr/share/nginx/html
# 自定义Nginx配置(解决Vue Router history模式刷新404 + 接口反向代理)
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 暴露容器内部80端口(仅容器内可见)
EXPOSE 80
# 启动Nginx(前台运行,避免容器退出)
CMD ["nginx", "-g", "daemon off;"]
补充:前端 Nginx 配置(关键)
创建frontend/nginx.conf,解决路由问题并代理后端接口:
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# 解决Vue3 Router history模式刷新404
location / {
try_files $uri $uri/ /index.html;
}
# 反向代理后端接口(前端请求/api全部转发到后端容器)
location /api {
proxy_pass http://backend:8080; # backend是Compose中后端服务名
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;
}
# 静态资源缓存(优化性能)
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 7d;
add_header Cache-Control "public, max-age=604800";
}
}
2. 后端 Dockerfile(SpringBoot 3.x)
路径:backend/Dockerfile(采用多阶段构建,减小镜像体积)
# 阶段1:构建SpringBoot项目
FROM maven:3.8.5-openjdk-17 as build-stage
WORKDIR /app
# 复制pom.xml和源码
COPY pom.xml ./
COPY src ./src
# 国内镜像源加速打包(替换为阿里云Maven仓库)
RUN mvn clean package -Dmaven.test.skip=true -Dmaven.repo.local=/root/.m2/repository -s /usr/share/maven/ref/settings-docker.xml
# 阶段2:运行SpringBoot项目(轻量JRE镜像)
FROM openjdk:17-jdk-slim
WORKDIR /app
# 从构建阶段复制打包好的jar包
COPY --from=build-stage /app/target/*.jar app.jar
# 暴露后端端口
EXPOSE 8080
# JVM优化参数(可选)
ENV JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom"
# 启动后端服务
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
后端示例接口(测试用)
在 SpringBoot 项目中编写一个简单接口,用于验证前后端通信:
// com.example.demo.controller.HelloController
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class HelloController {
@GetMapping("/hello")
public Map<String, Object> hello() {
Map<String, Object> result = new HashMap<>();
result.put("code", 200);
result.put("message", "Hello from SpringBoot Backend!");
result.put("data", "Vue3 + SpringBoot 部署成功");
return result;
}
}
SpringBoot 跨域配置(可选)
若未使用 Nginx 代理,需在后端添加跨域配置:
// com.example.demo.config.CorsConfig
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("http://127.0.0.1:8080");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", config);
return new CorsFilter(source);
}
}
四、编写 Docker Compose 文件(一键编排)
路径:docker-compose.yml(核心配置,实现一键启动)
version: '3.8'
# 定义服务集合
services:
# 前端服务
frontend:
# 基于前端目录的Dockerfile构建镜像
build: ./frontend
# 容器名称(便于管理)
container_name: vue3-frontend
# 重启策略:异常崩溃/服务器重启后自动启动(除非手动停止)
restart: unless-stopped
# 端口映射:仅绑定回环地址127.0.0.1,主机8080 → 容器80
# 关键:127.0.0.1限定仅本机可访问,外网无法连接
ports:
- "127.0.0.1:8080:80"
# 依赖后端服务,确保后端先启动
depends_on:
- backend
# 加入自定义网络(前后端容器互通)
networks:
- app-network
# 后端服务
backend:
# 基于后端目录的Dockerfile构建镜像
build: ./backend
container_name: springboot-backend
restart: unless-stopped
# 端口映射:仅绑定回环地址,主机8081 → 容器8080
ports:
- "127.0.0.1:8081:8080"
# 环境变量(可配置数据库地址、端口等)
environment:
- SPRING_PROFILES_ACTIVE=prod
- SERVER_PORT=8080
# 自定义网络
networks:
- app-network
# 自定义桥接网络(隔离外部网络,仅前后端容器互通)
networks:
app-network:
driver: bridge
核心配置说明
端口映射规则:
127.0.0.1:主机端口:容器端口例如
127.0.0.1:8080:80表示:仅本机可通过 8080 端口访问前端容器的 80 端口,外网无法访问,极大提升安全性。depends_on:保证后端服务先启动,避免前端请求时后端未就绪。
自定义网络:
app-network让前后端容器通过服务名(如backend)互通,无需手动配置 IP。
五、一键启动与运维命令
1. 启动服务(核心命令)
在vue3-springboot-demo根目录下执行:
# 首次启动:构建镜像 + 启动容器(后台运行)
docker-compose up -d --build
# 后续启动(无需重新构建镜像)
docker-compose up -d
-d:后台运行容器,不占用终端;--build:强制重新构建镜像(代码修改后需加此参数)。
2. 验证服务是否正常
# 查看容器运行状态
docker-compose ps
# 查看前端日志(排查前端问题)
docker-compose logs -f frontend
# 查看后端日志(排查后端问题)
docker-compose logs -f backend
# 测试后端接口(本机访问)
curl http://127.0.0.1:8081/api/hello
若返回如下 JSON,说明后端正常:
{"code":200,"data":"Vue3 + SpringBoot 部署成功","message":"Hello from SpringBoot Backend!"}
前端访问:打开浏览器输入 http://127.0.0.1:8080,即可看到 Vue3 页面,且能正常调用后端接口。
3. 常用运维命令
# 停止服务(保留容器,可重启)
docker-compose stop
# 重启服务
docker-compose restart
# 停止并删除容器(保留镜像)
docker-compose down
# 停止并删除容器 + 镜像(彻底清理)
docker-compose down --rmi all
# 查看容器资源占用
docker stats vue3-frontend springboot-backend
六、常见问题排查
1. 前端无法访问后端接口?
检查 Nginx 配置中的
proxy_pass是否为http://backend:8080(后端服务名 + 容器端口);确认后端服务监听地址为
0.0.0.0(SpringBoot 默认就是,无需修改);查看前端容器日志:
docker-compose logs frontend,检查 Nginx 是否启动正常。
2. 构建镜像时依赖下载慢?
前端:在
package.json中使用国内 npm 镜像(registry=https://registry.npmmirror.com);后端:在
pom.xml中添加阿里云 Maven 镜像源。
3. 端口被占用?
修改docker-compose.yml中的主机端口,例如将127.0.0.1:8080:80改为127.0.0.1:8082:80。
七、总结
通过
Dockerfile实现 Vue3/SpringBoot 的镜像标准化构建,解决了 “环境不一致” 的经典问题;docker-compose.yml实现一键编排,自动处理容器依赖、网络、端口映射,大幅降低部署复杂度;端口映射绑定
127.0.0.1,仅允许本机访问,在开发 / 测试环境中兼顾便捷性与安全性。
这套方案适用于本地开发、内网测试、小型个人项目部署,无需手动配置 Nginx、JDK、Node.js 等环境,真正做到 “一次编写,到处运行”。