Files
2026-09-21 17:11:35 +08:00

9.3 KiB
Raw Permalink Blame History

学生管理系统 Docker 部署说明

本次部署已在你的机器上实际执行并验证通过: MySQL、后端、前端三个容器均正常启动,浏览器访问 http://localhost 可用。 下方命令可直接复制执行。

一、部署架构

浏览器
  │  http://localhost
  ▼
┌────────────────────────────────┐
│ frontend   (node:20 → nginx:1.25) │  静态文件 /usr/share/nginx/html
└───────────┬────────────────────┘
            │ 反向代理(vue/nginx.conf 中已配置)
            │ /login /student /files ... → http://backend:9090
            ▼
┌────────────────────────────────┐
│ backend    (python:3.11-slim)   │  uvicorn main:app :9090
│                                  files/ 挂载到宿主机持久化
└───────────┬────────────────────┘
            │ aiomysql,DB_HOST=mysql
            ▼
┌────────────────────────────────┐
│ mysql      (mysql:8.0)          │  volume: student_mysql_data
│                                 库 student_system,启动时自动建表
└────────────────────────────────┘

二、本次新增的文件

文件 作用
student_system_2/docker-compose.yml 编排 mysql + backend + frontend 三个服务
student_system_2/.env 实际生效的环境变量(已按你本机端口占用情况配置)
student_system_2/.env.example 环境变量模板
student_system_2/fastapi-app/Dockerfile 后端镜像(Python 3.11 + uvicorn,暴露 9090)
student_system_2/fastapi-app/.dockerignore 排除 __pycache__、虚拟环境等
student_system_2/vue/Dockerfile 前端镜像(Node 20 编译 → Nginx 托管)
student_system_2/vue/.dockerignore 排除 node_modules、dist(关键:否则构建极慢)

vue/nginx.conf 是原有文件,直接复用,未做修改。其中代理目标写死为 http://backend:9090, 因此 compose 中后端服务名保持为 backend(已一致)。

镜像地址与端口

服务 镜像 容器名 宿主机端口
mysql mysql:8.0 student_system_2-mysql-1 13306 → 3306
backend student-system-backend:latest student_system_2-backend-1 9090
frontend student-system-frontend:latest student_system_2-frontend-1 80

三、环境准备

  1. 安装 Docker Desktop(Windows/macOS)或 Docker Engine + Compose 插件(Linux)。
  2. 验证:
docker --version
docker compose version

当前机器已确认:Docker 28.5.1 / Compose v2.40.2。

四、启动

在 student_system_2 目录(与 docker-compose.yml 同级)执行:

docker compose up -d --build

启动顺序由 depends_on 控制:MySQL 健康检查通过 → 启动 backend → 启动 frontend。 后端启动时自动建表(代码中 generate_schemas=True),无需手动执行迁移,已实测生成 admin / clazz / course / grade / major / notice / student / student_course 八张表。

查看状态:

docker compose ps        # 等待 backend、mysql 显示 (healthy)
docker compose logs -f   # Ctrl+C 退出,不影响容器运行

五、访问与验证

地址 说明
http://localhost 前端页面(登录/注册)
http://localhost:9090/docs 后端 Swagger 文档
http://localhost:9090/ 后端根路径
localhost:13306 MySQL(Navicat/DBeaver 可连,root / 123456)

六、日常运维命令

# 停止容器(保留数据)
docker compose stop

# 停止并删除容器与网络(数据卷保留,MySQL 数据不丢)
docker compose down

# 改完代码后重新构建并启动
docker compose up -d --build

# 只重启某个服务
docker compose restart backend

# 查看日志
docker compose logs -f backend

# 进入后端容器
docker compose exec backend bash

# 进入 MySQL 命令行
docker compose exec mysql mysql -uroot -p123456

# 查看资源占用
docker stats

说明:compose 未固定 container_name,容器名带项目前缀(student_system_2-xxx-1)。 因此请使用 docker compose exec <服务名> 而不是 docker exec <容器名>,更稳妥。

七、端口配置

你本机的 3306 已被本地 MySQL 占用(PID 6724),因此 .env 中已把容器内 3306 映射到宿主机 13306:

# student_system_2/.env
DB_NAME=student_system
DB_USER=root
DB_PASSWORD=123456

MYSQL_HOST_PORT=13306   # 容器内 3306 → 宿主机 13306
BACKEND_HOST_PORT=9090
FRONTEND_HOST_PORT=80   # 浏览器访问 http://localhost

修改端口后重新执行 docker compose up -d 即可生效。

八、数据持久化与备份

数据 位置 说明
MySQL 数据 Docker volume student_mysql_data 删除容器不丢,docker compose down -v 才会清除
上传的文件 宿主机 fastapi-app/files/ 与容器 /app/files 双向同步
# 备份数据库到当前目录
docker compose exec -T mysql mysqldump -uroot -p123456 student_system > backup.sql

# 从备份恢复
docker compose exec -T mysql mysql -uroot -p123456 student_system < backup.sql

# 查看数据卷明细
docker volume inspect student_mysql_data

九、旧部署遗留容器与数据迁移(重要)

你机器上还存在 旧目录名 student_system 时期部署的三个已停止容器, 它们的数据卷是独立保存的,本次部署没有删除或覆盖它们:

遗留对象 说明
容器 student-mysql / student-backend / student-frontend 均已 Exited
卷 student_system_mysql_data 旧 MySQL 数据
卷 student_system_upload_files 旧上传文件

新部署的数据库是全新的空库(表结构已自动创建,但无数据)。

如果不需要旧数据,可以清理掉这些遗留对象:

docker rm -f student-mysql student-backend student-frontend
docker volume rm student_system_mysql_data student_system_upload_files
docker rmi student_system-frontend student_system-backend

如果需要把旧数据迁移过来(旧部署用的同样是 root / 123456):

# 1) 用旧数据卷启动一个临时 MySQL(端口 13307,避免冲突)
docker run -d --name mysql-old -p 13307:3306 -e MYSQL_ROOT_PASSWORD=123456 ^
  -v student_system_mysql_data:/var/lib/mysql mysql:8.0

# 2) 等 30 秒左右待其就绪,导出旧数据
docker exec mysql-old mysqldump -uroot -p123456 student_system > old_data.sql

# 3) 导入到新库
docker compose exec -T mysql mysql -uroot -p123456 student_system < old_data.sql

# 4) 清理临时容器
docker rm -f mysql-old

Windows CMD 下换行符用 ^;PowerShell 下请写成一行。

十、常见问题排查

1. 前端页面打开报 502 / 接口失败

  • 检查:docker compose ps、docker compose logs backend
  • 确认 backend 与 frontend 同处 student-net 网络(compose 已配置)
  • 确认 nginx 代理目标仍为 http://backend:9090

2. 后端日志报 Can't connect to MySQL server

  • MySQL 首次初始化较慢,等其变为 healthy 后会自动重连;必要时 docker compose restart backend
  • 确认 DB_HOST=mysql(不能写 localhost,那是容器自身)
  • 确认 .env 中 DB_PASSWORD 与 MYSQL_ROOT_PASSWORD 一致

3. 后端报 Unknown database 'student_system'

  • 只有首次创建容器时才执行 MYSQL_DATABASE 建库。若数据卷已有旧数据则不会重建:
docker compose exec mysql mysql -uroot -p123456 -e "CREATE DATABASE IF NOT EXISTS student_system DEFAULT CHARSET utf8mb4;"

4. 端口被占用 Only one usage of each socket address / port is already allocated

  • 按第七节修改 .env 中的端口后重新 docker compose up -d
  • 查占用:netstat -ano | findstr :3306

5. 前端构建很慢或 npm ci 失败

  • 确保 vue/.dockerignore 含 node_modules/(否则会把本机依赖打进构建上下文)
  • 若 package-lock.json 与 package.json 不匹配,Dockerfile 已自动回退为 npm install
  • 换源构建:docker build --build-arg NPM_REGISTRY=https://registry.npmjs.org ./vue

6. 上传图片后访问 404

  • 确认宿主机 fastapi-app/files 目录存在且可写,映射路径为容器 /app/files

7. pip 安装慢

  • Dockerfile 默认使用清华源,可换源:docker build --build-arg PIP_INDEX_URL=https://pypi.org/simple ./fastapi-app

十一、生产环境建议

  1. 修改默认密码:务必修改 .env 中的 DB_PASSWORD,不要用 123456。
  2. 关闭 SQL 日志:把 fastapi-app/settings.py 中 "echo": True 改为 False,避免大量 SQL 日志拖慢性能。
  3. 不对宿主机暴露数据库:删除 compose 中 mysql 的 ports 映射(后端走内部网络即可)。
  4. 收敛 CORS:main.py 中 allow_origins=["*"] 建议改为实际前端域名。
  5. 启用 HTTPS:在 nginx 中增加 443 监听并配置证书。
  6. 限制日志体积:为各服务增加 logging.options.max-size / max-file。