Docker 化部署 Spring Boot + Vue 全栈应用:从打包到容器化上线
1. 引言
在现代软件开发中,容器化部署 已经成为主流。Docker 通过轻量级容器技术,解决了环境不一致、依赖冲突、部署复杂等问题。对于前后端分离项目(Spring Boot + Vue),使用 Docker 可以将前端、后端分别打包成镜像,并通过 docker-compose 一键启动整套应用,实现高效、可复用的交付。
本文将手把手带你:
- ✅ 将 Spring Boot 应用打包成 Docker 镜像
- ✅ 将 Vue 应用打包成 Nginx 镜像
- ✅ 使用 Docker Compose 编排前后端服务
- ✅ 配置网络、环境变量、数据持久化
- ✅ 生产环境优化建议
无论你是个人开发者还是团队成员,都能通过本文轻松掌握全栈应用的容器化部署。
2. 整体架构流程图
容器编排
Docker构建
开发环境
Spring Boot 源码
mvn clean package
生成 jar
Vue 源码
npm run build
生成 dist
编写 Dockerfile
基于 OpenJDK
构建后端镜像
docker build -t backend
编写 Dockerfile
基于 Nginx
构建前端镜像
docker build -t frontend
docker-compose.yml
docker-compose up -d
应用运行
3. 准备工作
3.1 环境要求
| 组件 | 版本 | 说明 |
|---|---|---|
| Docker | 20.10+ | 核心容器引擎 |
| Docker Compose | 2.20+ | 多容器编排(已集成于 Docker 官方) |
| JDK | 11 / 17 | 构建后端 jar |
| Node.js | 16+ | 构建前端 dist |
| Maven | 3.6+ | 构建后端(可选,也可用镜像内构建) |
3.2 项目结构示例
project/
├── backend/ # Spring Boot 项目
│ ├── src/
│ ├── pom.xml
│ └── Dockerfile
├── frontend/ # Vue 项目
│ ├── src/
│ ├── package.json
│ ├── vue.config.js
│ └── Dockerfile
├── docker-compose.yml
└── nginx.conf # 可选的 Nginx 自定义配置
4. 后端 Spring Boot 应用 Docker 化
4.1 打包 jar 文件
在项目根目录执行:
bash
cd backend
mvn clean package -DskipTests
生成的 jar 位于 target/xxx.jar。
4.2 编写 Dockerfile(多阶段构建优化)
创建 backend/Dockerfile:
dockerfile
# 第一阶段:构建(使用 Maven 镜像,可选)
FROM maven:3.8.4-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests
# 第二阶段:运行
FROM openjdk:11-jre-slim
WORKDIR /app
# 从构建阶段复制 jar
COPY --from=builder /app/target/*.jar app.jar
# 暴露端口
EXPOSE 8080
# 启动命令(可配置外部参数)
ENTRYPOINT ["java", "-jar", "app.jar"]
说明:使用多阶段构建可减小镜像体积,因为最终镜像只包含 JRE 和 jar,不包括 Maven 和源代码。
4.3 构建镜像
bash
docker build -t my-backend:1.0 ./backend
4.4 测试运行
bash
docker run -d -p 8080:8080 --name backend-test my-backend:1.0
访问 http://localhost:8080/actuator/health(如果有监控端点)验证。
5. 前端 Vue 应用 Docker 化
5.1 构建静态文件
bash
cd frontend
npm install
npm run build
生成 dist 目录,包含所有静态资源(HTML、CSS、JS)。
5.2 编写 Dockerfile(基于 Nginx)
创建 frontend/Dockerfile:
dockerfile
# 阶段1:构建(可选,如果宿主机已构建可直接复制)
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# 阶段2:Nginx 服务器
FROM nginx:alpine
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制自定义 Nginx 配置(可选)
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
如果宿主机已执行 npm run build,可以简化:
dockerfile
FROM nginx:alpine
COPY ./dist /usr/share/nginx/html
EXPOSE 80
5.3 自定义 nginx.conf(解决 Vue Router history 模式 404 问题)
创建 frontend/nginx.conf:
nginx
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 可选:后端 API 代理(也可以由前端调用真实后端地址)
location /api/ {
proxy_pass http://backend:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
注意:如果使用代理,需要确保后端服务名在 docker-compose 中定义为
backend。
5.4 构建前端镜像
bash
docker build -t my-frontend:1.0 ./frontend
5.5 测试运行
bash
docker run -d -p 80:80 --name frontend-test my-frontend:1.0
访问 http://localhost,应看到 Vue 首页。
6. 使用 Docker Compose 编排全栈应用
创建根目录下的 docker-compose.yml:
yaml
version: '3.8'
services:
# 后端服务
backend:
image: my-backend:1.0
container_name: backend
build: ./backend # 可动态构建
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/mydb?useSSL=false
depends_on:
- mysql
networks:
- app-network
# 前端服务
frontend:
image: my-frontend:1.0
container_name: frontend
build: ./frontend
ports:
- "80:80"
depends_on:
- backend
networks:
- app-network
# 数据库(可选)
mysql:
image: mysql:8.0
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: mydb
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
mysql-data:
6.1 启动所有服务
bash
docker-compose up -d
6.2 查看日志
bash
docker-compose logs -f
6.3 停止并删除容器
bash
docker-compose down -v # -v 会删除数据卷(注意数据丢失)
7. 生产环境优化建议
7.1 镜像体积优化
- 后端使用
eclipse-temurin:17-jre-alpine或openjdk:11-jre-slim替代完整 JDK。 - 前端使用
nginx:alpine,体积仅 20MB 左右。 - 多阶段构建去除构建工具和源码。
7.2 配置外部化
- 使用环境变量覆盖 Spring Boot 配置。
- 敏感信息(数据库密码)通过 Docker secrets 或环境变量注入,不要写死在镜像中。
7.3 健康检查
在 docker-compose.yml 中加入健康检查:
yaml
backend:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
7.4 日志管理
- 将容器日志输出到
stdout,由 Docker 日志驱动收集。 - 生产环境可配置
logging驱动为json-file或fluentd。
7.5 反向代理与 HTTPS
- 在前端 Nginx 中配置 SSL 证书。
- 可再增加一个
nginx-proxy服务统一入口。
8. 常见问题与排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 前端访问后端 API 出现跨域 | 前后端不同端口 | 配置 Nginx 反向代理,或后端添加 CORS 过滤器 |
| Vue 路由刷新 404 | history 模式下未配置 try_files | 修改 nginx.conf,添加 try_files $uri $uri/ /index.html; |
| 后端容器无法连接数据库 | 数据库 host 配置错误 | 使用 docker-compose 服务名(如 mysql)作为主机名 |
| 镜像构建失败 | Dockerfile 中 COPY 路径错误 | 检查上下文路径,确认文件存在 |
| 端口被占用 | 宿主机端口已被使用 | 修改 ports 映射到不同宿主机端口 |
9. 部署全景流程图
是
否
编写 Dockerfile
构建镜像
编写 docker-compose.yml
docker-compose up -d
测试访问
是否正常?
推送到镜像仓库
如 Harbor/Docker Hub
查看日志
调整配置
生产服务器拉取镜像并运行
10. 总结
通过 Docker 容器化部署 Spring Boot + Vue 全栈应用,我们可以获得以下收益:
- ✅ 环境一致性:开发、测试、生产环境完全相同,杜绝"在我机器上能跑"问题。
- ✅ 快速部署 :一条
docker-compose up命令即可启动所有服务。 - ✅ 可扩展性:轻松增加容器副本,结合 Kubernetes 实现弹性伸缩。
- ✅ 资源隔离:每个服务运行在独立的容器中,互不干扰。
最佳实践回顾:
- 前端使用 Nginx 镜像并提供自定义配置解决路由问题。
- 后端使用多阶段构建减小体积。
- 使用 Docker Compose 编排,定义网络和数据卷。
- 将配置(如数据库连接)通过环境变量传递,避免硬编码。
下一步:可以将镜像推送到私有仓库(如 Harbor),并配合 CI/CD(GitLab CI / Jenkins)实现自动化构建和部署。