1. 项目概述与背景
在现代Web应用开发中,前后端分离架构已成为主流模式。Spring Boot作为Java生态中最流行的后端框架,与Vue.js这一渐进式前端框架的组合,能够快速构建高性能的企业级应用。而Docker容器化技术则为这类应用的部署提供了标准化、可移植的解决方案。
我最近在客户项目中成功实施了一套基于Docker的Spring Boot + Vue全栈部署方案。相比传统部署方式,容器化部署将环境准备时间从2小时缩短到10分钟,且完全消除了"在我机器上能跑"的环境差异问题。下面将完整分享这套经过实战检验的部署方案。
2. 环境准备与工具选型
2.1 基础环境要求
- Docker Engine 20.10+(社区版即可)
- Docker Compose 1.29+
- JDK 11(推荐Amazon Corretto)
- Node.js 14+(推荐LTS版本)
- Maven 3.6+(用于后端打包)
提示:生产环境建议使用Docker的稳定版本,避免使用edge版本。Windows/macOS用户建议安装Docker Desktop,Linux用户可通过官方仓库安装。
2.2 项目结构设计
典型的前后端分离项目目录结构如下:
project-root/ ├── backend/ # Spring Boot项目 │ ├── src/ │ ├── pom.xml │ └── Dockerfile ├── frontend/ # Vue项目 │ ├── src/ │ ├── package.json │ └── Dockerfile └── docker-compose.yml # 编排配置文件这种结构清晰分离了前后端代码,每个组件都有自己的Dockerfile构建定义,最终通过docker-compose进行服务编排。
3. 后端Spring Boot容器化
3.1 Dockerfile配置
# 使用官方OpenJDK基础镜像 FROM amazoncorretto:11-alpine3.17 # 设置工作目录 WORKDIR /app # 复制Maven构建的jar包 COPY target/your-application.jar app.jar # 暴露服务端口 EXPOSE 8080 # 启动命令 ENTRYPOINT ["java","-jar","app.jar"]关键参数说明:
alpine版本镜像体积仅约150MB,远小于标准Linux镜像- 使用确定性的JDK版本(如11.0.18)而非latest标签
- 通过WORKDIR规范容器内路径
3.2 优化构建过程
在项目根目录执行以下命令构建镜像:
# 先打包Spring Boot应用 mvn clean package -DskipTests # 构建Docker镜像 docker build -t your-username/backend:1.0.0 -f backend/Dockerfile .构建优化技巧:
- 使用
.dockerignore文件排除不必要的文件(如IDE配置) - 多阶段构建可进一步减小镜像体积
- 版本标签应遵循语义化版本规范
4. 前端Vue项目容器化
4.1 Dockerfile配置
# 构建阶段 FROM node:16-alpine as build-stage WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 生产阶段 FROM nginx:1.23-alpine COPY --from=build-stage /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80这个多阶段构建方案:
- 第一阶段使用Node镜像编译Vue项目
- 第二阶段使用轻量级Nginx镜像
- 最终镜像仅包含编译后的静态文件
4.2 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; } }此配置实现了:
- 静态文件服务
- 前端路由支持(history模式)
- 后端API代理(解决跨域)
5. Docker Compose编排
5.1 完整编排文件
version: '3.8' services: backend: image: your-username/backend:1.0.0 container_name: backend ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=prod networks: - app-network frontend: image: your-username/frontend:1.0.0 container_name: frontend ports: - "80:80" depends_on: - backend networks: - app-network networks: app-network: driver: bridge5.2 关键配置解析
- 网络配置:自定义bridge网络使容器可通过服务名通信
- 依赖管理:前端服务显式依赖后端服务
- 环境变量:传递Spring Boot的profile配置
- 端口映射:前端80端口对外暴露,后端8080仅在内部访问
6. 部署与运维实践
6.1 一键部署命令
# 启动所有服务(后台模式) docker-compose up -d # 查看运行状态 docker-compose ps # 查看日志 docker-compose logs -f6.2 生产环境建议
资源限制:为容器配置CPU/内存限制
deploy: resources: limits: cpus: '0.5' memory: 512M健康检查:添加应用健康检查
healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3日志管理:配置日志驱动和轮转
logging: driver: "json-file" options: max-size: "10m" max-file: "3"
7. 常见问题排查
7.1 前端无法访问后端API
现象:浏览器控制台出现CORS错误
解决方案:
- 确认nginx配置中的
proxy_pass地址正确 - 检查后端服务的
@CrossOrigin注解配置 - 验证docker网络连通性:
docker exec -it frontend curl http://backend:8080/api/health
7.2 静态资源加载404
现象:页面空白或部分资源加载失败
排查步骤:
- 进入前端容器检查文件是否存在:
docker exec -it frontend ls -l /usr/share/nginx/html - 确认Vue项目的
publicPath配置 - 检查nginx的
root指令路径
7.3 容器启动顺序问题
现象:前端启动时后端尚未就绪
优化方案:
- 使用
depends_on结合健康检查 - 在前端添加启动等待脚本:
// 在main.js中添加 const waitFor = (url, timeout = 30000) => { const start = Date.now() return new Promise((resolve) => { const attempt = () => { fetch(url) .then(resolve) .catch(() => { if (Date.now() - start >= timeout) { console.error(`Timeout waiting for ${url}`) resolve() } else { setTimeout(attempt, 1000) } }) } attempt() }) } waitFor(process.env.VUE_APP_API_URL + '/health').then(() => { new Vue({ /* ... */ }).$mount('#app') })
8. 性能优化实践
8.1 镜像构建优化
多阶段构建:如前所示,大幅减小最终镜像体积
层缓存优化:将不常变化的操作放在前面
# 先复制package.json并安装依赖 COPY package*.json ./ RUN npm install # 然后复制其他文件 COPY . .使用.dockerignore:
node_modules .git *.md .idea
8.2 运行时优化
JVM参数调优:
ENTRYPOINT ["java", "-Xms256m", "-Xmx512m", "-jar", "app.jar"]Nginx性能调优:
events { worker_connections 1024; } http { gzip on; gzip_types text/plain application/json; }容器资源监控:
docker stats docker-compose top
9. 安全加固措施
9.1 镜像安全
定期更新基础镜像
FROM amazoncorretto:11.0.18-alpine3.17 # 明确版本号使用非root用户运行
RUN addgroup -S springboot && adduser -S springboot -G springboot USER springboot
9.2 网络防护
限制不必要的端口暴露
# 只暴露前端80端口 ports: - "80:80"配置网络隔离
networks: app-network: internal: true # 禁止外部访问
9.3 密钥管理
使用Docker secrets或环境变量文件
env_file: - .env.production避免在镜像中硬编码敏感信息
10. 持续集成与部署
10.1 GitHub Actions示例
name: Build and Deploy on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 # 构建后端 - name: Build Backend run: | cd backend mvn package -DskipTests docker build -t your-username/backend:${{ github.sha }} . # 构建前端 - name: Build Frontend run: | cd frontend npm install npm run build docker build -t your-username/frontend:${{ github.sha }} . # 推送镜像 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Push Images run: | docker push your-username/backend:${{ github.sha }} docker push your-username/frontend:${{ github.sha }}10.2 部署策略
蓝绿部署:通过负载均衡切换流量
滚动更新:逐步替换旧容器
docker-compose pull docker-compose up -d版本回滚:
docker-compose up -d --force-recreate --no-deps frontend=your-username/frontend:old-version
在实际项目中,这套Docker化部署方案使我们的部署效率提升了80%,环境一致性达到100%。特别是在团队协作和CI/CD流水线中,容器化的优势更加明显。对于需要快速迭代的全栈项目,这种部署方式值得推荐。