从零开始!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 就能直接访问你的绝美项目!

相关推荐
Victor3564 小时前
MongoDB(52)如何配置分片?
后端
Victor3564 小时前
MongoDB(53)什么是分片键?
后端
薛定谔的悦10 小时前
MQTT通信协议业务层实现的完整开发流程
java·后端·mqtt·struts
enjoy嚣士11 小时前
springboot之Exel工具类
java·spring boot·后端·easyexcel·excel工具类
无限大611 小时前
职场逻辑03:3步搞定高效汇报,让领导看到你的价值
后端
盐水冰12 小时前
【烘焙坊项目】后端搭建(12) - 订单状态定时处理,来单提醒和顾客催单
java·后端·学习
紫丁香12 小时前
AutoGen详解一
后端·python·flask
小涛不学习12 小时前
Spring Boot 详解(从入门到原理)
java·spring boot·后端
Victor35614 小时前
MongoDB(51)什么是分片?
后端