从零开始!Vue3+SpringBoot前后端分离项目Docker部署实战(中):Spring Boot后端与Docker Compose串联

📝 前言

上一篇文章中,我们已经在 CentOS 服务器上配置好了 Docker,并优雅地实现了 MySQL 数据的一键初始化和持久化。

本篇我们将继续向核心迈进:把我们的 Spring Boot 后端项目进行打包镜像化,同时利用 Docker Compose 的网络特性,让后端容器能够无需任何修改,动态连上海我们的数据库容器。


☕ 第一步:编写 Spring Boot 的 Dockerfile

在我们的项目里,后端是典型的基于 Maven 构建的 Spring Boot 项目。为了减少手动在宿主机敲 mvn clean package 的环境依赖问题,我们采用 Dockerfile 多阶段构建(Multi-stage build)

backend/SpringBoot/Dockerfile 这个路径下创建文件,写入以下内容:

dockerfile 复制代码
# --------- 阶段1:构建阶段 ---------
# 使用带 Maven 和 JDK 8 的镜像环境来打包我们的项目(采用国内镜像源加速拉取)
FROM docker.m.daocloud.io/maven:3.8.6-openjdk-8 AS build
WORKDIR /app

# 为了利用 Docker 缓存,先单独拷贝 pom.xml 并下载依赖
COPY pom.xml .
# 强制指定阿里云 Maven 镜像源下载依赖(大幅提升构建速度)
RUN mvn dependency:go-offline -B -Dmaven.repo.local=/root/.m2/repository -s /usr/share/maven/conf/settings.xml \
    || mvn dependency:go-offline -B

# 拷贝全部源码并跳过测试打包
COPY src ./src
RUN mvn clean package -DskipTests

# --------- 阶段2:运行阶段 ---------
# 打包完成后,我们只需要一个精简的 JRE 环境即可运行,抛弃笨重的 Maven
FROM docker.m.daocloud.io/openjdk:8-jre-alpine
WORKDIR /app

# 设置时区,防止 Java 取到 UTC 时间导致数据库插入时间少了8小时
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    apk add --no-cache tzdata && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

# 把 第一阶段 编译好的 jar 包复制过来
COPY --from=build /app/target/*.jar app.jar

# 暴露 8080 端口
EXPOSE 8080

# 启动容器
ENTRYPOINT ["java", "-jar", "app.jar"]

🤔 为什么要用"多阶段构建"?

极大地缩小了最终的镜像体积!如果直接把源码和 Maven 全部塞进镜像,打出来的镜像可能高达 600MB+,而多阶段构建下,最终的系统里只有精简版的 JRE 和一个 jar包,通常只有一百多兆。既安全又节省资源。


🔗 第二步:Docker Compose 编排魔法

有了打包脚本,我们现在要在外部的主 docker-compose.yml 中将后端容器加入进去,并告诉它"数据库在哪里"。不要用宿主机 IP!我们要用 服务名 (service name) 进行连接。

继续向你的 docker-compose.yml 补充后端的部分:

yaml 复制代码
services:
  # ... MySQL配置在上一篇中有,这里省略 ...

  project001-backend:
    build:
      context: ./backend/SpringBoot   # 指向刚刚写了 Dockerfile 的目录
      dockerfile: Dockerfile
    container_name: project001-backend
    restart: always
    # 这个 depends_on 极其重要!
    # 结合上一篇里 MySQL 的 healthcheck,它能保证后端容器等数据库彻底准备好才启动,
    # 避免一上来 Spring Boot 启动太快连不上没准备好的数据库直接崩溃
    depends_on:
      project001-mysql:
        condition: service_healthy 
    environment:
      TZ: Asia/Shanghai
      # Spring Boot 在启动时会优先读取这里的环境变量,覆盖默认的 application.yml
      # 重点看连接中的 project001-mysql,我们直接以容器名作为域名即可互通!
      SPRING_DATASOURCE_URL: jdbc:mysql://project001-mysql:3306/campus_maintenance_sys?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: ${MYSQL_ROOT_PASSWORD} # 从 .env 全局读取
    ports:
      - "8080:8080" # 左边代表宿主机端口,右边是容器内端口
    volumes:
      - ./backend/SpringBoot/uploads:/app/uploads # 映射用户上传的文件目录,防止重启容器后文件丢失

💧 妙用 Environment 覆盖

在本地开发时,你可能在 application.yml 里写死了 url: jdbc:mysql://localhost:3306...

但在容器里是不能填 localhost 的,否则后端容器会去寻找自己的 3306 端口,直接报错。

借助 Docker Compose 注入 SPRING_DATASOURCE_XXX,Docker 内置的机制会无缝覆盖 Spring Boot 的 spring.datasource 属性,**这也就是我们实现了"一份代码多处执行无痛部署"的精髓!**不需要在代码里写一大堆判断,统统通过编排文件注入!


🏃 第三步:启动并验证

此时在带 .env 的项目根目录下敲下:

bash 复制代码
docker compose up -d --build project001-backend

在终端可以使用 docker logs -f project001-backend 动态查看启动日志。如果你看到了熟悉的:

text 复制代码
Started CampusMaintenanceSystemApplication in 3.4 seconds (JVM running for 3.8)

恭喜你!这说明后端已经顺利构建完毕,并且成功连接上我们构建的 MySQL 数据库,等待响应了。

🎯 总结

本篇我们解决了 Java 构建环境的隔离问题以及容器互联。目前后端和数据库系统已经是一套完美运行的小生态。但在现代前后端分离架构中,用户不可能直接访问 8080 端口玩无厘头的 API 数据。

下一篇(下篇)将是重头戏,我会带你把 Vue3 Vite 跑在 Nginx 中,甚至连代理跨域问题一并解决,真正实现输入公网 IP 就能直接访问你的绝美项目!

相关推荐
阳光是sunny8 小时前
别再被 worktree 绕晕了!AI 编程时代你必须掌握的 Git 隔离神器
前端·人工智能·后端
万少10 小时前
万少的博客 - 技术分享与解决方案
前端·javascript·后端
咖啡八杯10 小时前
GoF设计模式——备忘录模式
java·后端·spring·设计模式
苍何10 小时前
腾讯再放大招,企微 Agent 大圆开启内测
后端
ethantan10 小时前
一篇讲解AI Agent 组成:像人一样思考的智能体
人工智能·后端·程序员
Cosolar12 小时前
vLLM 生产级部署完全指南
人工智能·后端·架构
IT_陈寒13 小时前
垃圾回收器选错了,我的Java服务内存炸了
前端·人工智能·后端
用户83562907805113 小时前
使用 Python 在 PDF 中创建与管理书签
后端·python
Nturmoils13 小时前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端
大志说编程13 小时前
Agent面试真题06: 十分钟带你快速掌握Agent记忆管理高频面试题(附详细答案)
后端·面试·ai编程