从零到云:我的 SpringBoot+Vue 考试系统 Docker 化全记录
前言
作为一个刚毕业的计算机专业学生,我一直在思考如何把自己的毕设项目——基于 SpringBoot+Vue 的在线考试系统——从本地开发环境迁移到生产环境。传统的部署方式需要手动配置 JDK、MySQL、Nginx,换台机器就要重新折腾一遍,效率低且容易出错。
直到我接触了 Docker,这一切变得简单起来。
这篇文章记录了我将整个考试系统 Docker 化的完整过程:从编写 Dockerfile、本地多容器联调,到推送到阿里云镜像仓库,最后让其他人也能一键部署。
如果你也想把自己的项目容器化,希望这篇实战记录能帮你少走弯路。
一、项目背景
我的在线考试系统采用前后端分离架构:
• 后端:Spring Boot 2.x + MyBatis-Plus + MySQL 5.7
• 前端:Vue 2 + Element UI
• 数据库:MySQL 5.7,数据库名 online_exam_2026
在本地开发时,我直接运行 mvn spring-boot:run 和 npm run serve,但这种方式有几个问题:
1. 依赖环境不一致,换台电脑可能跑不起来
2. 数据库需要手动安装配置
3. 部署到服务器需要重复配置环境
Docker 化可以一次性解决这些问题。
二、环境准备
2.1 操作系统
我使用的是 CentOS 7,运行在 VMware 虚拟机中。
2.2 安装 Docker
CentOS 7 默认仓库里的 Docker 版本太旧(1.13),需要先卸载旧版本,再安装 Docker CE 26.1.4。
// bash
# 卸载旧版本
sudo yum remove docker docker-common docker-selinux docker-engine
# 安装依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加 Docker 仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 安装 Docker CE
sudo yum install -y docker-ce docker-ce-cli containerd.io
# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 验证安装
docker --version
# 输出:Docker version 26.1.4, build ...
踩坑记录:CentOS 7 的内核版本较低,安装新版 Docker 时可能会遇到兼容性问题。我参考了 Docker 官方文档,使用 --setopt=obsoletes=0 参数解决了依赖冲突。
三、项目打包
3.1 后端打包
Spring Boot 项目需要打包成可执行的 JAR 文件。
踩坑警告:确保 pom.xml 中配置了 spring-boot-maven-plugin,否则打包出来的 JAR 没有主类清单,运行时会报错 no main manifest attribute。
// xml
<!-- pom.xml 中必须包含 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
执行打包命令:
// bash
cd ~/exam-system-docker/ExamSystem/OnlineExamSystemApi
mvn clean package -DskipTests
打包成功后,target/ 目录下会生成 OnlineExamSystemApi-1.0.jar。
3.2 前端打包
Vue 项目需要构建生成静态文件。
// bash
cd ~/exam-system-docker/ExamSystem/OnlineExamSystemVue
npm install
npm run build
构建完成后,dist/ 目录包含所有静态资源。
四、编写 Dockerfile
4.1 后端 Dockerfile
我采用多阶段构建(multi-stage build),第一阶段用 Maven 编译,第二阶段用轻量的 JRE 运行,这样可以显著减小镜像体积。
// dockerfile
# 阶段1:Maven 构建
FROM maven:3.8-openjdk-8 AS builder
WORKDIR /build
# 先复制 pom.xml,利用 Docker 缓存
COPY pom.xml .
RUN mvn dependency:go-offline -B
# 复制源码并构建
COPY src ./src
RUN mvn clean package -DskipTests -B
# 阶段2:运行环境
FROM openjdk:8-jre-slim
WORKDIR /app
# 从构建阶段复制 jar 包
COPY --from=builder /build/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
关键设计点:
• 使用 maven:3.8-openjdk-8 作为构建环境,确保 JDK 版本一致
• 先复制 pom.xml 并下载依赖,利用 Docker 层缓存,后续构建更快
• 运行阶段使用 openjdk:8-jre-slim,体积更小
最终镜像大小:656MB
4.2 前端 Dockerfile
同样使用多阶段构建,Node.js 编译,nginx 提供静态文件服务。
// dockerfile
# 阶段1:Node 构建
FROM node:14 AS builder
WORKDIR /build
# 复制依赖文件
COPY package.json yarn.lock ./
RUN yarn install --frozen-lockfile
# 复制源码并构建
COPY . .
RUN yarn build
# 阶段2:nginx 提供静态文件
FROM nginx:alpine
# 复制构建产物
COPY --from=builder /build/dist /usr/share/nginx/html
# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
4.3 Nginx 配置
前端需要反向代理后端 API,配置如下:
// nginx
server {
listen 80;
server_name localhost;
# 前端静态文件
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# 反向代理后端 API
location /api/ {
proxy_pass http://backend:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
注意:proxy_pass http://backend:8080/ 中的 backend 是 docker-compose 中定义的服务名,Docker 网络会自动解析。
最终镜像大小:74.7MB
五、docker-compose 编排
三个容器需要协同工作,使用 docker-compose 可以一键启动。
// yaml
version: '3.8'
services:
# MySQL 数据库
mysql:
image: mysql:5.7
container_name: exam-mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: online_exam_2026
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
- ./online_exam.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- exam-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
# 后端 API
backend:
build: ./OnlineExamSystemApi
container_name: exam-backend
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/online_exam_2026?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
depends_on:
mysql:
condition: service_healthy
networks:
- exam-network
restart: on-failure
# 前端
frontend:
build: ./OnlineExamSystemVue
container_name: exam-frontend
ports:
- "80:80"
depends_on:
- backend
networks:
- exam-network
volumes:
mysql-data:
networks:
exam-network:
driver: bridge
关键配置说明:
1. MySQL 容器:
◦ 使用 healthcheck 确保数据库完全启动后再启动后端
◦ 自动导入 online_exam.sql 初始化数据库
◦ 数据持久化到 mysql-data 卷
2. 后端容器:
◦ 通过环境变量覆盖数据库连接配置,指向 mysql 容器
◦ depends_on 配合 healthcheck 确保启动顺序
3. 前端容器:
◦ 映射 80 端口,访问 http://localhost 即可
六、本地构建与启动
6.1 构建镜像
// bash
cd ~/exam-system-docker/ExamSystem
docker-compose build
首次构建会下载基础镜像,需要一些时间。后续构建会利用缓存,速度很快。
6.2 启动所有服务
// bash
docker-compose up -d
-d 参数表示后台运行。
6.3 查看运行状态
// bash
docker-compose ps
输出:
Name Command State Ports
----------------------------------------------------------------------
exam-backend java -jar app.jar Up 0.0.0.0:8080->8080/tcp
exam-frontend nginx -g daemon off; Up 0.0.0.0:80->80/tcp
exam-mysql docker-entrypoint.sh Up 0.0.0.0:3306->3306/tcp
6.4 访问系统
打开浏览器,访问 http://192.168.120.131(你的虚拟机 IP),即可看到考试系统登录页面。
默认账号:
• 管理员:9991 / 123456
• 教师:20081001 / 123456
• 学生:2022084 / 123456
七、推送到阿里云镜像仓库
本地部署成功后,我把镜像推送到阿里云容器镜像服务(ACR),方便在其他机器上部署。
7.1 登录阿里云 ACR
// bash
docker login crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com --username=nick0477683133
输入密码后看到 Login Succeeded 表示登录成功。
7.2 打 tag
// bash
# 后端镜像
docker tag examsystem-backend:latest crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com/fantastic6-exam/examsystem-backend:v1
# 前端镜像
docker tag examsystem-frontend:latest crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com/fantastic6-exam/examsystem-frontend:v1
踩坑记录:命名空间必须是阿里云控制台中已创建的,否则会报 denied: requested access to the resource is denied。我的命名空间是 fantastic6-exam,需要提前在控制台创建。
7.3 推送镜像
// bash
docker push crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com/fantastic6-exam/examsystem-backend:v1
docker push crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com/fantastic6-exam/examsystem-frontend:v1
后端镜像 656MB,前端镜像 74.7MB,推送需要几分钟,取决于网络速度。
八、其他人如何部署
现在任何人都可以一键部署我的考试系统了!
8.1 前提条件
• 安装 Docker 和 docker-compose
• 网络能访问阿里云镜像仓库
8.2 创建 docker-compose.yml
在任意目录创建 docker-compose.yml:
// yaml
version: '3.8'
services:
mysql:
image: mysql:5.7
container_name: exam-mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: online_exam_2026
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
networks:
- exam-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
backend:
image: crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com/fantastic6-exam/examsystem-backend:v1
container_name: exam-backend
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/online_exam_2026?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: root
depends_on:
mysql:
condition: service_healthy
networks:
- exam-network
restart: on-failure
frontend:
image: crpi-paclr97bkf1e2svc.cn-qingdao.personal.cr.aliyuncs.com/fantastic6-exam/examsystem-frontend:v1
container_name: exam-frontend
ports:
- "80:80"
depends_on:
- backend
networks:
- exam-network
volumes:
mysql-data:
networks:
exam-network:
driver: bridge
注意:这里使用 image 直接引用阿里云镜像,不需要 build 字段。
8.3 下载并初始化数据库
由于数据库初始化脚本没有打包在镜像中,需要手动下载并导入。
// bash
# 下载 SQL 文件(假设你托管在 GitHub 或其他地方)
wget https://your-repo.com/online_exam.sql
# 启动 MySQL 容器
docker-compose up -d mysql
# 等待 MySQL 完全启动后,导入数据
docker exec -i exam-mysql mysql -uroot -proot online_exam_2026 < online_exam.sql
8.4 启动所有服务
// bash
docker-compose up -d
等待镜像下载完成(首次约 700MB),然后访问 http://你的服务器IP 即可。
8.5 登录系统
• 管理员:9991 / 123456
• 教师:20081001 / 123456
• 学生:2022084 / 123456
九、总结与收获
9.1 完成的工作
✅ 编写后端 Dockerfile(多阶段构建,656MB)
✅ 编写前端 Dockerfile(多阶段构建,74.7MB)
✅ 编写 docker-compose.yml 编排三容器
✅ 本地三容器联调成功
✅ 推送到阿里云镜像仓库
✅ 实现一键部署方案
9.2 踩过的坑
1. Spring Boot 打包失败:忘记配置 spring-boot-maven-plugin,导致 JAR 无主类清单
2. Docker 镜像名大小写:镜像名必须小写,ExamSystem 会报错
3. 命名空间不存在:推送时报 denied,需要先在阿里云控制台创建命名空间
4. 数据库连接失败:后端启动时 MySQL 还没准备好,使用 healthcheck + depends_on 解决
十、资源链接
• Docker 官方文档:https://docs.docker.com/
• 阿里云容器镜像服务:https://www.aliyun.com/product/acr
写在最后
从一个本地跑起来的项目,到容器化部署、推送到云端,这个过程让我对 Docker 有了更深入的理解。
Docker 不仅仅是"打包工具",它改变了我对软件交付的认知:一次构建,到处运行。
如果你也有自己的项目想要容器化,不妨从写一个简单的 Dockerfile 开始。遇到问题时,多查文档,多动手实验,踩过的坑都会变成宝贵的经验。
如果这篇文章对你有帮助,欢迎点赞、收藏、分享。有任何问题,欢迎在评论区交流讨论!
更多推荐




所有评论(0)