Spring Boot+Vue项目Docker容器化实战指南
1. 项目概述
最近在帮朋友公司重构一个前后端分离的管理系统,技术栈选用了Spring Boot + Vue的组合。考虑到后续的部署维护成本,决定采用Docker容器化方案。这种部署方式在实际生产环境中已经非常普遍,但新手在初次尝试时往往会遇到各种"坑"。今天我就把这次实战中的完整流程和关键注意事项整理出来,希望能帮到有类似需求的开发者。
这个方案最大的优势在于环境隔离和快速部署。传统部署方式需要手动安装JDK、Nginx等依赖,而Docker方案只需要几条命令就能完成全栈环境的搭建。我们最终实现的效果是:前端Vue项目打包后由Nginx提供服务,后端Spring Boot应用运行在独立的容器中,两者通过Docker网络通信,整个系统可以通过docker-compose一键启停。
2. 环境准备与工具选型
2.1 基础环境配置
在开始之前,需要确保宿主机已经安装以下工具:
- Docker 20.10+(社区版即可)
- Docker Compose 1.29+
- JDK 11(用于本地开发调试)
- Node.js 14+(用于前端开发)
注意:生产环境建议使用Linux服务器,本文以CentOS 7为例。Windows系统需要特别注意文件路径和换行符问题。
我推荐使用以下版本组合,经过实际生产验证:
$ docker --version Docker version 20.10.17, build 100c701 $ docker-compose --version docker-compose version 1.29.2, build 5becea4c2.2 项目结构设计
合理的项目结构能大幅降低后期维护成本。我们的项目结构如下:
project-root/ ├── backend/ # Spring Boot项目 │ ├── src/ │ ├── Dockerfile │ └── pom.xml ├── frontend/ # Vue项目 │ ├── public/ │ ├── src/ │ ├── Dockerfile │ └── package.json ├── nginx/ # Nginx配置 │ └── default.conf └── docker-compose.yml # 编排文件这种结构将前后端完全分离,每个组件有自己的Dockerfile,最终通过docker-compose统一管理。相比将前后端打包到一个容器中的方案,这种设计更符合微服务理念,也便于独立扩展。
3. Spring Boot后端容器化
3.1 Dockerfile编写
后端Dockerfile有几个关键点需要注意:
# 使用多阶段构建减小镜像体积 FROM maven:3.8.6-jdk-11 AS build WORKDIR /app COPY pom.xml . # 先单独复制pom.xml并下载依赖,利用Docker缓存 RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests # 运行时阶段 FROM openjdk:11-jre-slim WORKDIR /app COPY --from=build /app/target/*.jar app.jar # 时区设置 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 健康检查 HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1 EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]这个Dockerfile有几个优化点:
- 使用多阶段构建,最终镜像只包含JRE而非完整的JDK,体积从300MB+减少到100MB左右
- 先单独复制pom.xml下载依赖,利用Docker缓存机制加速后续构建
- 添加健康检查,方便容器编排系统监控服务状态
- 设置时区,避免容器内时间与宿主机不一致的问题
3.2 常见问题解决
在实际构建过程中可能会遇到以下问题:
问题1:Maven构建缓慢解决方案:可以在Dockerfile中添加阿里云镜像:
RUN sed -i 's|https://repo.maven.apache.org|https://maven.aliyun.com/repository/public|g' /usr/share/maven/conf/settings.xml问题2:时区不正确虽然Dockerfile中设置了时区,但某些基础镜像可能缺少时区数据。可以改用:
RUN apt-get update && apt-get install -y tzdata问题3:内存不足Spring Boot应用默认会占用较多内存,可以在docker-compose中限制:
deploy: resources: limits: memory: 1024M4. Vue前端容器化
4.1 前端Dockerfile优化
前端项目的容器化有几个特殊考虑:
# 构建阶段 FROM node:16-alpine AS build WORKDIR /app COPY package*.json ./ RUN npm install --registry=https://registry.npm.taobao.org COPY . . RUN npm run build # 生产阶段 FROM nginx:1.21-alpine COPY --from=build /app/dist /usr/share/nginx/html COPY nginx/default.conf /etc/nginx/conf.d/default.conf EXPOSE 80关键优化点:
- 使用Alpine基础镜像,大幅减小镜像体积
- 设置国内npm镜像加速构建
- 分离构建阶段和运行阶段,最终镜像只包含静态文件和Nginx
- 自定义Nginx配置解决前端路由问题
4.2 Nginx关键配置
前端项目通常需要特殊处理路由问题,以下是nginx/default.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; } }这个配置实现了两个重要功能:
- 处理Vue Router的history模式,通过try_files确保刷新页面不返回404
- 将/api开头的请求代理到后端服务,解决跨域问题
5. Docker Compose编排
5.1 完整编排文件
docker-compose.yml将前后端服务整合:
version: '3.8' services: backend: build: ./backend container_name: app-backend restart: unless-stopped ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=prod - TZ=Asia/Shanghai networks: - app-network frontend: build: ./frontend container_name: app-frontend restart: unless-stopped ports: - "80:80" depends_on: - backend networks: - app-network networks: app-network: driver: bridge5.2 编排技巧解析
- 网络配置:创建自定义网络app-network,使容器间可以通过服务名通信(如backend:8080)
- 依赖管理:通过depends_on控制启动顺序,但要注意这不能确保服务已完全就绪
- 环境变量:传递Spring Boot的profile配置和时区设置
- 重启策略:unless-stopped确保容器异常退出时自动重启
重要提示:生产环境应该添加资源限制和健康检查,完整示例:
deploy: resources: limits: cpus: '0.5' memory: 512M restart_policy: condition: on-failure6. 部署与运维实践
6.1 一键部署命令
完整的部署流程只需要三个步骤:
# 1. 构建镜像 docker-compose build # 2. 启动服务 docker-compose up -d # 3. 查看日志 docker-compose logs -f6.2 生产环境优化建议
镜像管理:
- 使用docker-compose pull获取最新镜像
- 定期清理无用镜像:docker image prune -a -f
日志收集:
logging: driver: "json-file" options: max-size: "10m" max-file: "3"数据持久化: 如果应用有文件上传功能,需要挂载卷:
volumes: - ./uploads:/app/uploads健康检查: 在docker-compose中扩展健康检查:
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3
6.3 性能监控方案
建议部署以下监控组件:
cAdvisor:容器资源监控
docker run -d --name=cadvisor \ -v /:/rootfs:ro \ -v /var/run:/var/run:ro \ -v /sys:/sys:ro \ -v /var/lib/docker/:/var/lib/docker:ro \ -p 8081:8080 \ google/cadvisorPortainer:可视化容器管理
docker run -d -p 9000:9000 \ -v /var/run/docker.sock:/var/run/docker.sock \ portainer/portainer
7. 常见问题排查指南
7.1 启动问题排查
问题:容器启动后立即退出排查步骤:
- 查看日志:docker logs <container_id>
- 检查端口冲突:netstat -tulnp | grep 8080
- 检查依赖服务是否就绪:docker-compose logs backend
问题:前端无法访问后端API解决方案:
- 确保docker-compose中使用了自定义网络
- 检查Nginx配置中的proxy_pass地址是否正确
- 在容器内测试连通性:docker exec -it frontend curl http://backend:8080/api/health
7.2 性能问题排查
问题:应用响应缓慢排查命令:
# 查看容器资源使用 docker stats # 进入容器分析 docker exec -it backend bash top -H -p $(pgrep java)优化建议:
- 调整JVM参数:-Xmx512m -Xms512m
- 增加容器资源限制
- 检查数据库连接池配置
7.3 安全加固措施
避免使用root用户运行容器:
USER 1000:1000定期更新基础镜像:
docker-compose build --no-cache --pull敏感信息管理:
env_file: - .env.production
8. 进阶优化方案
8.1 使用CI/CD自动化流程
推荐GitLab CI示例配置:
stages: - build - deploy build_backend: stage: build script: - docker build -t backend-image ./backend deploy_prod: stage: deploy only: - master script: - scp docker-compose.yml user@server:/app - ssh user@server "cd /app && docker-compose pull && docker-compose up -d"8.2 镜像瘦身进阶技巧
使用JLink定制JRE:
RUN jlink --add-modules java.base,java.logging \ --strip-debug \ --no-man-pages \ --no-header-files \ --compress=2 \ --output /opt/jre-minimal前端使用多阶段构建+压缩:
RUN npm install -g compression-webpack-plugin && \ npm run build -- --mode production
8.3 灰度发布方案
通过docker-compose实现蓝绿部署:
services: backend-v1: image: backend:1.0 networks: - app-network backend-v2: image: backend:2.0 networks: - app-network frontend: depends_on: - backend-v2切换流量只需更新frontend的depends_on并重启。
9. 项目迁移与扩展
9.1 传统项目迁移指南
迁移已有项目到Docker的步骤:
- 分析现有依赖:ldd /path/to/binary
- 创建Dockerfile逐步添加依赖
- 测试容器内功能完整性
- 调整配置文件路径
9.2 微服务扩展方案
当需要扩展为微服务架构时:
- 每个服务独立Dockerfile
- 使用docker-compose.override.yml管理不同环境
- 添加API网关服务
- 集成服务发现(Consul/Eureka)
示例扩展结构:
project-root/ ├── auth-service/ ├── user-service/ ├── product-service/ ├── gateway/ └── docker-compose.yml9.3 数据库容器化建议
生产环境数据库部署建议:
db: image: postgres:13-alpine volumes: - pg_data:/var/lib/postgresql/data environment: POSTGRES_PASSWORD_FILE: /run/secrets/db_password secrets: - db_password secrets: db_password: file: ./secrets/db_password.txt关键注意事项:
- 必须配置数据卷持久化
- 使用secrets管理敏感信息
- 建议单独部署数据库容器
- 定期备份卷数据