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

相关推荐
翱翔-蓝天1 分钟前
WSL + Docker + GPU 安装 video-subtitle-remover 完整文档
运维·docker·容器
江湖有缘5 分钟前
PanCheck 容器化部署:自建网盘链接检测服务全流程
docker
SCBAiotAigc12 分钟前
2026.4.10:docker desktop内网环境安装教程
人工智能·docker·容器·具身智能
海兰22 分钟前
【springboot】gradle快速镜像配置
spring boot·笔记·后端
饼瑶24 分钟前
Isaac Sim 5.0.0 Docker 部署手册(实验室服务器)
服务器·docker·容器
武超杰27 分钟前
SpringBoot 整合 Spring Security 实现权限控制
spring boot·后端·spring
XMYX-034 分钟前
06 - Go 的切片、字典与遍历:从原理到实战
后端·golang
wb18935 分钟前
docker-ce容器技术重习
运维·笔记·docker·容器·云计算
架构师专栏36 分钟前
比 MQ 更轻的异步方案:Spring 内置的这个隐藏功能,很多人还不知道
后端
Aric_Jones38 分钟前
从实战理解异步、并发并行与GIL:FastAPI vs SpringBoot
java·spring boot·fastapi