三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

Spring Boot+Vue项目Docker容器化部署实践

Spring Boot+Vue项目Docker容器化部署实践

1. 项目概述

在现代化Web应用开发中,前后端分离架构已成为主流模式。Spring Boot作为Java生态中最流行的后端框架,与Vue.js这一渐进式前端框架的组合,能够快速构建高性能的企业级应用。而Docker容器化技术则为这类应用的部署提供了标准化、可移植的解决方案。

我最近为一个电商平台项目完成了从开发到部署的全流程,其中使用Docker部署Spring Boot + Vue项目的实践让我收获颇丰。这种部署方式相比传统部署具有明显优势:

  • 环境一致性:开发、测试、生产环境完全一致
  • 资源隔离:避免端口冲突和依赖污染
  • 快速扩展:轻松实现水平扩展和负载均衡
  • 版本管理:镜像版本控制方便回滚

2. 环境准备与工具选型

2.1 基础环境配置

在开始部署前,需要确保开发环境满足以下要求:

  1. 操作系统:推荐使用Linux(Ubuntu 20.04+)或macOS,Windows需启用WSL2
  2. Docker环境
    # 安装Docker Engine curl -fsSL https://get.docker.com | sh # 启动Docker服务 sudo systemctl enable --now docker # 验证安装 docker --version
  3. Docker Compose:建议安装v2.x版本
    sudo curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose

2.2 项目结构规划

合理的项目结构是成功部署的基础。我采用的典型结构如下:

project-root/ ├── backend/ # Spring Boot项目 │ ├── src/ │ ├── Dockerfile │ └── pom.xml ├── frontend/ # Vue项目 │ ├── src/ │ ├── Dockerfile │ └── package.json ├── docker-compose.yml # 编排配置文件 └── nginx/ # 反向代理配置 └── default.conf

注意:实际项目中,建议将敏感配置(如数据库密码)通过环境变量或Docker secrets管理,不要硬编码在配置文件中。

3. Spring Boot后端容器化

3.1 编写Dockerfile

Spring Boot应用的Dockerfile需要关注几个关键点:

# 使用官方OpenJDK镜像作为基础 FROM eclipse-temurin:17-jdk-jammy as builder # 设置工作目录 WORKDIR /app # 复制构建文件 COPY pom.xml . COPY src ./src # 构建应用(使用Maven缓存层) RUN --mount=type=cache,target=/root/.m2 \ mvn clean package -DskipTests # 生产阶段 FROM eclipse-temurin:17-jre-jammy WORKDIR /app # 从构建阶段复制jar包 COPY --from=builder /app/target/*.jar app.jar # 暴露端口 EXPOSE 8080 # 启动命令 ENTRYPOINT ["java", "-jar", "app.jar"]

关键优化点:

  1. 使用多阶段构建减小镜像体积
  2. 利用构建缓存加速后续构建
  3. 使用轻量级的JRE镜像而非JDK

3.2 配置优化建议

在application.properties/yml中添加容器化专用配置:

server: port: 8080 servlet: context-path: /api compression: enabled: true spring: datasource: url: jdbc:mysql://mysql:3306/app_db?useSSL=false username: ${DB_USER} password: ${DB_PASSWORD} jpa: hibernate: ddl-auto: update show-sql: true

4. Vue前端容器化

4.1 前端Dockerfile配置

Vue项目的容器化需要处理静态资源构建和服务:

# 构建阶段 FROM node:16-alpine as builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # 生产阶段 FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html COPY nginx/default.conf /etc/nginx/conf.d/default.conf EXPOSE 80

4.2 Nginx关键配置

nginx/default.conf需要配置API代理:

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: ./backend ports: - "8080:8080" environment: - DB_USER=root - DB_PASSWORD=secret depends_on: mysql: condition: service_healthy networks: - app-network frontend: build: ./frontend ports: - "80:80" depends_on: - backend networks: - app-network mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: app_db volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s timeout: 10s retries: 5 networks: - app-network volumes: mysql_data: networks: app-network: driver: bridge

5.2 启动与维护命令

常用操作命令:

# 构建并启动所有服务 docker-compose up -d --build # 查看日志 docker-compose logs -f # 停止服务 docker-compose down # 更新特定服务 docker-compose up -d --no-deps --build frontend

6. 高级部署方案

6.1 生产环境优化建议

  1. 使用独立数据库服务:生产环境建议使用云数据库而非容器内MySQL
  2. 配置TLS加密:通过Let's Encrypt添加HTTPS支持
  3. 日志收集:配置ELK或Fluentd收集容器日志
  4. 监控告警:集成Prometheus + Grafana监控系统

6.2 多阶段部署流程

典型CI/CD流程示例:

  1. 开发环境:使用docker-compose进行本地开发
  2. 测试环境:通过GitLab CI构建镜像并部署到测试集群
  3. 生产环境:使用Kubernetes编排,蓝绿部署策略

7. 常见问题排查

7.1 连接问题诊断

问题现象:前端无法访问后端API

排查步骤

  1. 检查容器网络连通性:
    docker network inspect app-network
  2. 验证后端服务健康状态:
    curl http://backend:8080/actuator/health
  3. 检查Nginx代理配置:
    docker exec -it frontend nginx -t

7.2 性能优化技巧

  1. 镜像构建加速

    # 在Dockerfile中添加构建缓存 RUN --mount=type=cache,target=/root/.m2 \ mvn clean package
  2. 前端静态资源缓存

    location /assets { expires 1y; add_header Cache-Control "public"; }
  3. JVM调优

    ENTRYPOINT ["java", "-Xms512m", "-Xmx1024m", "-jar", "app.jar"]

8. 安全最佳实践

  1. 最小权限原则

    FROM eclipse-temurin:17-jre-jammy USER nobody
  2. 镜像扫描

    docker scan my-spring-app
  3. 密钥管理

    # 在docker-compose中使用secrets services: backend: secrets: - db_password secrets: db_password: file: ./secrets/db_password.txt
  4. 网络隔离

    networks: app-network: internal: true

9. 实际部署经验分享

在最近的项目中,我们遇到了几个值得分享的情况:

  1. 时区问题:容器默认使用UTC时间,需要在Dockerfile中显式设置:

    ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
  2. 前端路由问题:Vue的history模式需要特殊Nginx配置:

    location / { try_files $uri $uri/ /index.html; }
  3. Spring Boot热部署:开发时可以使用DevTools配合volume挂载:

    services: backend: volumes: - ./backend:/app environment: - SPRING_DEVTOOLS_REMOTE_SECRET=mysecret
  4. 镜像标签策略:建议使用语义化版本控制:

    docker build -t myapp/backend:1.0.0-$(git rev-parse --short HEAD) .

10. 监控与日志管理

10.1 基础监控配置

  1. Spring Boot Actuator

    management: endpoints: web: exposure: include: "*" endpoint: health: show-details: always
  2. 容器资源监控

    docker stats

10.2 集中式日志方案

使用Fluentd收集日志的docker-compose配置示例:

services: fluentd: image: fluent/fluentd volumes: - ./fluentd.conf:/fluentd/etc/fluent.conf ports: - "24224:24224" backend: logging: driver: "fluentd" options: fluentd-address: "fluentd:24224" tag: "backend"

对应的fluentd.conf配置:

<source> @type forward port 24224 </source> <match *> @type stdout </match>

11. 扩展部署模式

11.1 多环境配置管理

使用docker-compose.override.yml管理不同环境:

# 生产环境 docker-compose -f docker-compose.yml -f docker-compose.prod.yml up # 开发环境 docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

11.2 Kubernetes部署准备

创建基本的k8s部署描述文件:

backend-deployment.yaml:

apiVersion: apps/v1 kind: Deployment metadata: name: backend spec: replicas: 3 selector: matchLabels: app: backend template: metadata: labels: app: backend spec: containers: - name: backend image: myrepo/backend:1.0.0 ports: - containerPort: 8080 envFrom: - configMapRef: name: backend-config

frontend-service.yaml:

apiVersion: v1 kind: Service metadata: name: frontend spec: type: LoadBalancer ports: - port: 80 targetPort: 80 selector: app: frontend

12. 持续集成实践

12.1 GitHub Actions示例

前端CI流水线配置示例:

name: Frontend CI on: push: branches: [ main ] paths: - 'frontend/**' jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Build Docker image run: | cd frontend docker build -t myrepo/frontend:${{ github.sha }} . - name: Login to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Push image run: docker push myrepo/frontend:${{ github.sha }}

12.2 镜像扫描与安全

在CI中加入安全扫描步骤:

- name: Scan for vulnerabilities run: | docker scan --file frontend/Dockerfile myrepo/frontend:${{ github.sha }} docker scan --file backend/Dockerfile myrepo/backend:${{ github.sha }}

13. 性能调优实战

13.1 JVM内存配置

针对Spring Boot容器的内存优化:

# 根据容器内存限制自动计算JVM参数 ENV JAVA_OPTS="-XX:MaxRAMPercentage=75.0 -XX:+UseContainerSupport -XX:+UseG1GC" ENTRYPOINT exec java $JAVA_OPTS -jar app.jar

13.2 Nginx性能调优

调整frontend容器的Nginx配置:

events { worker_connections 1024; } http { sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; gzip on; gzip_types text/plain text/css application/json application/javascript; server { # 原有配置... } }

14. 备份与恢复策略

14.1 数据库备份方案

使用cron定期备份MySQL数据:

services: mysql-backup: image: mysql:8.0 volumes: - ./backups:/backups - mysql_data:/var/lib/mysql command: > bash -c 'while true; do sleep 86400 && mysqldump -h mysql -u root -p$$MYSQL_ROOT_PASSWORD --all-databases > /backups/backup-$$(date +%Y%m%d).sql done' environment: MYSQL_ROOT_PASSWORD: secret networks: - app-network

14.2 配置文件版本控制

重要配置管理建议:

  1. 将docker-compose.yml纳入Git版本控制
  2. 使用配置模板+环境变量的方式管理差异配置
  3. 敏感信息使用Docker secrets或Vault管理

15. 网络与安全加固

15.1 防火墙配置

限制不必要的网络访问:

# 只允许80/443端口访问前端 docker network create --driver bridge --opt com.docker.network.bridge.enable_icc=false app-network

15.2 TLS证书配置

使用Let's Encrypt自动获取证书:

services: certbot: image: certbot/certbot volumes: - ./letsencrypt:/etc/letsencrypt - ./nginx/certs:/etc/letsencrypt/webrootauth command: certonly --webroot -w /etc/letsencrypt/webrootauth -d example.com --email admin@example.com --agree-tos --non-interactive --keep-until-expiring

更新Nginx配置使用HTTPS:

server { listen 443 ssl; server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # 原有配置... }

16. 多节点部署方案

16.1 Swarm模式部署

初始化Swarm集群:

docker swarm init

部署服务栈:

docker stack deploy -c docker-compose.yml myapp

16.2 负载均衡配置

使用Traefik作为边缘路由器:

services: traefik: image: traefik:v2.5 command: - --providers.docker - --entrypoints.web.address=:80 ports: - "80:80" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro frontend: labels: - "traefik.http.routers.frontend.rule=Host(`example.com`)" - "traefik.http.services.frontend.loadbalancer.server.port=80"

17. 存储方案选型

17.1 持久化存储策略

生产环境存储建议:

  1. 数据库数据:使用云提供商块存储或高性能NAS
  2. 上传文件:使用S3兼容对象存储
  3. 配置文件:使用ConfigMap或环境变量

17.2 本地开发存储优化

开发时使用bind mount提高性能:

services: backend: volumes: - ./backend:/app - m2-repo:/root/.m2 volumes: m2-repo:

18. 自动化测试集成

18.1 容器化测试方案

在CI中加入测试阶段:

services: backend-test: build: context: ./backend target: builder command: mvn test depends_on: mysql: condition: service_healthy

18.2 端到端测试配置

使用Cypress进行前端测试:

services: e2e: image: cypress/included:9.5.0 depends_on: - frontend - backend environment: - CYPRESS_BASE_URL=http://frontend volumes: - ./e2e:/e2e working_dir: /e2e command: npx cypress run

19. 本地开发优化

19.1 热重载配置

前端开发时启用热更新:

services: frontend-dev: build: context: ./frontend target: development volumes: - ./frontend:/app - /app/node_modules ports: - "3000:3000" command: npm run serve

对应的开发Dockerfile:

FROM node:16-alpine as development WORKDIR /app COPY package*.json ./ RUN npm install CMD ["npm", "run", "serve"]

19.2 开发工具集成

配置远程开发环境:

// .vscode/launch.json { "version": "0.2.0", "configurations": [ { "type": "docker-node", "request": "attach", "name": "Debug Frontend", "port": 9229, "address": "localhost", "localRoot": "${workspaceFolder}/frontend", "remoteRoot": "/app" } ] }

20. 项目迁移与升级

20.1 版本升级策略

安全升级Docker基础镜像:

  1. 定期扫描镜像漏洞
  2. 使用dependabot自动更新依赖
  3. 遵循语义化版本控制

20.2 数据迁移方案

数据库迁移示例:

# 导出旧数据 docker exec old_mysql mysqldump -u root -psecret app_db > backup.sql # 导入新数据库 docker exec -i new_mysql mysql -u root -psecret app_db < backup.sql

21. 成本优化实践

21.1 镜像大小优化

减小Spring Boot镜像的技巧:

  1. 使用JLink创建自定义JRE
  2. 移除不必要的依赖
  3. 使用Alpine基础镜像

21.2 资源限制配置

在docker-compose中设置资源限制:

services: backend: deploy: resources: limits: cpus: '1' memory: 1G reservations: memory: 512M

22. 文档与知识管理

22.1 项目文档自动化

使用Swagger生成API文档:

@SpringBootApplication @OpenAPIDefinition(info = @Info(title = "API文档", version = "1.0")) public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

22.2 部署流程图

使用PlantUML记录架构:

@startuml node "前端" as front node "后端" as back node "数据库" as db front -> back : API请求 back -> db : 数据存取 @enduml

23. 团队协作规范

23.1 开发规范建议

  1. 镜像标签规范<项目>-<服务>:<版本>-<环境>
  2. 环境变量命名:全大写+下划线,如DB_HOST
  3. 端口分配:统一维护端口映射表

23.2 代码审查要点

Dockerfile审查清单:

  1. 是否使用最新基础镜像?
  2. 是否包含不必要的权限?
  3. 是否有敏感信息泄露风险?
  4. 是否遵循了最小化原则?

24. 监控告警配置

24.1 Prometheus监控

Spring Boot配置:

management: endpoints: web: exposure: include: prometheus,health,info metrics: tags: application: ${spring.application.name}

Prometheus配置示例:

scrape_configs: - job_name: 'backend' metrics_path: '/actuator/prometheus' static_configs: - targets: ['backend:8080']

24.2 告警规则示例

监控容器内存使用:

groups: - name: container.rules rules: - alert: HighMemoryUsage expr: container_memory_usage_bytes{container_label_com_docker_compose_service="backend"} > 1GB for: 5m labels: severity: warning annotations: summary: "High memory usage on backend service"

25. 日志分析实践

25.1 结构化日志配置

Spring Boot logback配置:

<configuration> <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="net.logstash.logback.encoder.LogstashEncoder"/> </appender> <root level="INFO"> <appender-ref ref="JSON"/> </root> </configuration>

25.2 日志查询技巧

使用ELK查询日志示例:

{ "query": { "bool": { "must": [ { "match": { "container_name": "backend" }}, { "range": { "@timestamp": { "gte": "now-1h" }}} ] } } }

26. 扩展功能集成

26.1 消息队列集成

添加RabbitMQ服务:

services: rabbitmq: image: rabbitmq:3-management ports: - "5672:5672" - "15672:15672" environment: RABBITMQ_DEFAULT_USER: admin RABBITMQ_DEFAULT_PASS: secret

Spring Boot配置:

spring: rabbitmq: host: rabbitmq port: 5672 username: admin password: secret

26.2 缓存服务集成

添加Redis服务:

services: redis: image: redis:6 ports: - "6379:6379" volumes: - redis_data:/data volumes: redis_data:

27. 多环境配置管理

27.1 环境变量管理

使用env_file分离配置:

services: backend: env_file: - .env.backend.prod

.env.backend.prod示例:

DB_HOST=mysql-prod.cluster.example.com DB_PORT=3306 REDIS_HOST=redis-prod

27.2 配置中心集成

使用Nacos作为配置中心:

services: nacos: image: nacos/nacos-server ports: - "8848:8848" environment: MODE: standalone

Spring Boot配置:

spring: cloud: nacos: config: server-addr: nacos:8848 file-extension: yaml

28. 安全审计与合规

28.1 镜像安全扫描

定期扫描策略:

# 使用Trivy扫描镜像 docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image myapp/backend:latest

28.2 合规性检查

使用dockle进行合规检查:

docker run --rm -v /var/run/docker.sock:/var/run/docker.sock goodwithtech/dockle myapp/backend:latest

29. 性能基准测试

29.1 压力测试配置

使用k6进行负载测试:

services: k6: image: loadimpact/k6 volumes: - ./tests:/tests command: run /tests/loadtest.js

示例测试脚本:

import http from 'k6/http'; import { check, sleep } from 'k6'; export default function() { let res = http.get('http://frontend/api/products'); check(res, { 'status is 200': (r) => r.status === 200 }); sleep(1); }

29.2 性能指标收集

关键监控指标:

  1. 容器CPU/内存使用率
  2. API响应时间(P99)
  3. 数据库查询性能
  4. 前端资源加载时间

30. 项目总结与演进

经过多个项目的实践验证,这种Docker化的Spring Boot+Vue部署方案展现出显著优势:

  1. 效率提升:新成员能在30分钟内搭建完整开发环境
  2. 稳定性增强:生产环境问题复现率降低90%
  3. 扩展灵活:轻松支持从单机到集群的扩展

未来可能的演进方向:

  1. 向Service Mesh架构迁移
  2. 实现自动弹性伸缩
  3. 集成更多云原生组件

在实际操作中,我发现几个特别值得注意的细节:

  • 开发阶段使用docker-compose.override.yml管理本地特殊配置
  • 生产环境一定要配置资源限制防止单个容器耗尽主机资源
  • 定期清理无用镜像和卷释放磁盘空间
← 返回列表