9.3 KiB
学生管理系统 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 |
三、环境准备
- 安装 Docker Desktop(Windows/macOS)或 Docker Engine + Compose 插件(Linux)。
- 验证:
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
十一、生产环境建议
- 修改默认密码:务必修改
.env中的DB_PASSWORD,不要用123456。 - 关闭 SQL 日志:把
fastapi-app/settings.py中"echo": True改为False,避免大量 SQL 日志拖慢性能。 - 不对宿主机暴露数据库:删除 compose 中
mysql的ports映射(后端走内部网络即可)。 - 收敛 CORS:
main.py中allow_origins=["*"]建议改为实际前端域名。 - 启用 HTTPS:在 nginx 中增加 443 监听并配置证书。
- 限制日志体积:为各服务增加
logging.options.max-size/max-file。