1. 为什么选择Docker部署Spring Boot + Vue项目?
在当今的Web开发领域,前后端分离架构已经成为主流模式。Spring Boot作为Java生态中最流行的后端框架,与Vue这一渐进式JavaScript前端框架的组合,被广泛应用于企业级应用开发。而Docker作为容器化技术的代表,为这种架构的部署带来了革命性的便利。
传统部署方式通常需要在服务器上手动安装JDK、Node.js、Nginx等依赖环境,配置过程繁琐且容易出错。我曾经在一个客户项目中,因为服务器环境差异导致部署失败,花了整整两天时间排查环境问题。而Docker通过容器化技术将应用及其所有依赖打包在一起,实现了"一次构建,到处运行"的承诺。
2. 项目架构与准备工作
2.1 技术栈分析
我们的项目采用典型的前后端分离架构:
- 后端:Spring Boot 2.7.x(建议版本)
- 前端:Vue 3.x + Vite(比Webpack更快的构建工具)
- 数据库:MySQL 8.0(也可替换为PostgreSQL)
- 容器化:Docker 20.10+ & Docker Compose
2.2 开发环境准备
在开始之前,确保你的开发机已安装:
- Docker Desktop(Windows/Mac)或Docker Engine(Linux)
# 验证Docker安装 docker --version docker-compose --version - JDK 17(Spring Boot 2.7+推荐版本)
- Node.js 16+(Vue 3.x要求)
注意:生产环境建议使用Linux服务器,资源占用更少,性能更好。我曾遇到Windows服务器因内存不足导致容器频繁崩溃的问题。
3. Spring Boot后端Docker化
3.1 创建Dockerfile
在Spring Boot项目根目录创建Dockerfile:
# 第一阶段:构建 FROM maven:3.8.6-eclipse-temurin-17 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # 第二阶段:运行 FROM eclipse-temurin:17-jre WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]这个多阶段构建Dockerfile有两个关键优化:
- 使用
dependency:go-offline提前下载依赖,避免每次构建都重新下载 - 基础镜像从jdk改为jre,减少镜像体积约150MB
3.2 配置生产环境参数
在application.properties中添加:
spring.profiles.active=prod server.port=8080 # 数据库配置将在Docker Compose中通过环境变量注入3.3 构建并测试镜像
docker build -t spring-boot-app . docker run -p 8080:8080 spring-boot-app4. Vue前端Docker化
4.1 优化Vue构建配置
在vite.config.js中增加生产配置:
export default defineConfig({ base: '/', // 根据实际部署路径调整 build: { outDir: 'dist', assetsDir: 'static', chunkSizeWarningLimit: 1600, }, server: { proxy: { '/api': { target: 'http://backend:8080', // 注意这里使用服务名 changeOrigin: true } } } })4.2 创建前端Dockerfile
# 构建阶段 FROM node:16-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 生产阶段 FROM nginx:1.23-alpine COPY --from=build /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 804.3 配置Nginx
创建nginx.conf:
server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }5. 使用Docker Compose编排服务
5.1 编写docker-compose.yml
version: '3.8' services: backend: build: context: ./spring-boot-backend dockerfile: Dockerfile container_name: spring-boot-app environment: - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/app_db?useSSL=false - SPRING_DATASOURCE_USERNAME=root - SPRING_DATASOURCE_PASSWORD=123456 ports: - "8080:8080" depends_on: - mysql networks: - app-network frontend: build: context: ./vue-frontend dockerfile: Dockerfile container_name: vue-app ports: - "80:80" depends_on: - backend networks: - app-network mysql: image: mysql:8.0 container_name: mysql environment: - MYSQL_ROOT_PASSWORD=123456 - MYSQL_DATABASE=app_db volumes: - mysql-data:/var/lib/mysql networks: - app-network volumes: mysql-data: networks: app-network: driver: bridge5.2 关键配置解析
- 网络配置:自定义的
app-network让容器可以通过服务名互相访问 - 数据持久化:MySQL数据通过volume持久化,避免容器重启数据丢失
- 依赖顺序:使用
depends_on控制启动顺序
6. 部署与优化实践
6.1 一键部署命令
docker-compose up -d --build6.2 生产环境优化建议
镜像大小优化:
- 使用alpine基础镜像
- 多阶段构建
- 清理构建缓存
性能调优:
# 在docker-compose.yml中添加资源限制 services: backend: deploy: resources: limits: cpus: '2' memory: 1G日志管理:
docker-compose logs -f backend
7. 常见问题排查指南
7.1 容器启动失败
现象:容器立即退出
排查步骤:
- 查看日志:
docker logs <container_id> - 常见原因:
- 端口冲突:
Address already in use - 数据库连接失败
- 内存不足(特别是Windows/Mac)
- 端口冲突:
7.2 前端无法访问API
现象:API请求404
解决方案:
- 检查Nginx配置中的
proxy_pass地址 - 确保后端服务名称与docker-compose中一致
- 跨域问题可在Spring Boot中添加配置:
@Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*"); } }; }
7.3 数据库连接问题
现象:Communications link failure
解决方法:
- 确保MySQL容器已启动
- 检查连接URL中的容器服务名
- 增加连接超时配置:
spring.datasource.hikari.connection-timeout=30000
8. 进阶部署方案
8.1 使用CI/CD自动化流程
推荐GitHub Actions配置示例:
name: Build and Deploy on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Build and push run: | docker-compose -f docker-compose.prod.yml build docker-compose -f docker-compose.prod.yml push8.2 监控与运维
健康检查:
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3使用Prometheus监控:
// Spring Boot中添加依赖 implementation 'io.micrometer:micrometer-registry-prometheus'日志收集:
services: backend: logging: driver: "json-file" options: max-size: "10m" max-file: "3"
在实际项目中,我通常会先在小规模环境测试所有配置,再逐步扩展到生产环境。特别是在网络策略和资源限制方面,需要根据实际业务负载进行调整。记住,没有放之四海皆准的完美配置,最适合你的才是最好的。