服务地址:
http://<内网IP>:5019
# 启动所有服务
docker compose up -d
# 停止所有服务
docker compose down
# 重启所有服务
docker compose restart
# 重启单个服务
docker compose restart app
docker compose restart queue
docker compose restart pdf-worker
# 查看运行状态
docker compose ps
# 查看进程状态(nginx + php-fpm)
docker exec math_cms_app ps aux | grep -E "nginx|php-fpm"
# 1. 查看 Laravel 应用日志(最常用)
docker exec math_cms_app tail -100 storage/logs/laravel.log
# 实时查看
docker exec math_cms_app tail -f storage/logs/laravel.log
# 2. 查看容器日志(Nginx + PHP-FPM)
docker logs math_cms_app --tail 100
# 实时查看
docker logs -f math_cms_app
# 3. 查看 PHP 错误日志
docker exec math_cms_app tail -100 /var/log/php-fpm/error.log
# 4. 查看 Nginx 错误日志
docker exec math_cms_app tail -100 /var/log/nginx/error.log
# 5. 筛选特定关键词
docker exec math_cms_app tail -500 storage/logs/laravel.log | grep -i "error\|exception\|fail"
# 6. 查看今天的日志(如果按日期分割)
docker exec math_cms_app cat storage/logs/laravel-$(date +%Y-%m-%d).log | tail -100
# 7. 快速排查智能组卷问题
docker exec math_cms_app tail -200 storage/logs/laravel.log | grep -i "智能\|intelligent\|assemble\|error"
# 查看最近日志
docker exec math_cms_app tail -100 storage/logs/laravel.log
# 只看 ERROR 级别
docker exec math_cms_app grep "\.ERROR" storage/logs/laravel.log | tail -50
# 实时监控日志
docker exec math_cms_app tail -f storage/logs/laravel.log
# 清空日志
docker exec math_cms_app truncate -s 0 storage/logs/laravel.log
# 组合:先显示最近 200 行,然后实时监控
docker exec math_cms_app tail -200f storage/logs/laravel.log
# 访问日志(看请求状态码)
docker exec math_cms_app tail -100 /var/log/nginx/access.log
# 错误日志
docker exec math_cms_app tail -50 /var/log/nginx/error.log
# 只看 5xx 错误的请求
docker exec math_cms_app grep '" 5[0-9][0-9] ' /var/log/nginx/access.log | tail -30
# 慢请求日志(超过5秒的请求)
docker exec math_cms_app cat /var/log/php-fpm-slow.log 2>/dev/null || echo "暂无慢请求"
# 查看队列 Worker 日志
docker logs math_cms_queue --tail=50
docker logs math_cms_pdf --tail=50
# 实时监控 PDF 队列
docker logs -f math_cms_pdf
docker exec math_cms_app sh -c "echo '=== Laravel Errors ===' && grep '\.ERROR' storage/logs/laravel.log | tail -10 && echo '=== Nginx 5xx ===' && grep '\" 5[0-9][0-9] ' /var/log/nginx/access.log | tail -5"
系统支持两种部署模式:
| 模式 | 说明 | 适用场景 | 耗时 |
|---|---|---|---|
| Quick | 代码卷映射,无需重新构建 | 日常代码更新 | 10-30秒 |
| Build | 完整构建 Docker 镜像 | 首次部署、依赖更新、Dockerfile 变更 | 5-10分钟 |
| 服务器类型 | 基础文件 | Mount 文件 |
|---|---|---|
| 主服务器 | docker-compose.yml |
docker-compose.mount.yml |
| PDF 服务器 | docker-compose.pdf.yml |
docker-compose.pdf.mount.yml |
| API 服务器 | docker-compose.api.yml |
docker-compose.api.mount.yml |
cd ansible
# 快速部署(默认)
./deploy.sh # 所有服务器
./deploy.sh quick pdf # 只部署 PDF 服务器
./deploy.sh quick api # 只部署 API 服务器
./deploy.sh quick main # 只部署主服务器
# 完整构建
./deploy.sh build # 所有服务器
./deploy.sh build pdf # 只部署 PDF 服务器
./deploy.sh build api # 只部署 API 服务器
./deploy.sh build main # 只部署主服务器
# 其他命令
./deploy.sh test # 测试服务器连接
./deploy.sh status # 查看服务器状态
./deploy.sh help # 查看帮助
# Build 模式(完整构建)
docker compose -f docker-compose.yml build
docker compose -f docker-compose.yml up -d --force-recreate
# Quick 模式(代码卷映射)
docker compose -f docker-compose.yml -f docker-compose.mount.yml up -d --force-recreate
# Build 模式(完整构建)
docker compose -f docker-compose.pdf.yml build
docker compose -f docker-compose.pdf.yml up -d --force-recreate
# Quick 模式(代码卷映射)
docker compose -f docker-compose.pdf.yml -f docker-compose.pdf.mount.yml up -d --force-recreate
# Build 模式(完整构建)
docker compose -f docker-compose.api.yml build
docker compose -f docker-compose.api.yml up -d --force-recreate
# Quick 模式(代码卷映射)
docker compose -f docker-compose.api.yml -f docker-compose.api.mount.yml up -d --force-recreate
首次部署必须先 build 创建镜像,之后才能使用 quick 模式:
# 1. 拉取代码
git clone <repo> /srv/www/math_cms
cd /srv/www/math_cms
# 2. 配置环境
cp .env.example .env
# 编辑 .env 配置数据库等
# 3. 构建镜像(以 API 服务器为例)
docker compose -f docker-compose.api.yml build
# 4. 启动容器(使用 quick 模式)
docker compose -f docker-compose.api.yml -f docker-compose.api.mount.yml up -d
# 1. 拉取最新代码
git fetch origin && git reset --hard origin/main
# 2. 重启容器(以 API 服务器为例)
docker compose -f docker-compose.api.yml -f docker-compose.api.mount.yml up -d --force-recreate
# 3. 清除缓存
docker exec math_cms_app php artisan optimize:clear
build,镜像里有 vendor、node_modules、public/build# 进入容器清理 Laravel 缓存
docker exec math_cms_app php artisan optimize:clear
# 重启队列(代码更新后必须)
docker compose restart queue pdf-worker
# 清理临时文件
docker exec math_cms_app rm -rf storage/app/temp/*
# 查看容器资源使用
docker stats --no-stream
# 进入容器调试
docker exec -it math_cms_app sh
# 测试数据库连接
docker exec math_cms_app php artisan db:show
# 测试 Redis 连接
docker exec math_cms_app php artisan tinker --execute="dump(app('redis')->ping());"
# 测试 Chrome(PDF 生成)
docker exec math_cms_pdf chromium-browser --version
# 查看失败的队列任务
docker exec math_cms_app php artisan queue:failed
# 重试失败的任务
docker exec math_cms_app php artisan queue:retry all
# 查看失败任务详情
docker exec math_cms_app php artisan tinker --execute="\$job = DB::table('failed_jobs')->latest()->first(); echo \$job->exception ?? 'no failed jobs';"
# CPU 满载 - 停止 PDF 服务
docker compose stop pdf-worker
# 强制杀死所有 Chrome 进程
docker exec math_cms_pdf pkill -9 chromium
# 清理临时文件
docker exec math_cms_pdf rm -rf /tmp/chrome-profile-*
docker exec math_cms_pdf rm -rf /tmp/exam_pdf_*
# 重启 PDF 服务
docker compose restart pdf-worker
# 修复 storage 权限问题
docker exec math_cms_app chmod -R 777 /app/storage
# 检查 Web 服务
curl http://localhost:5019/health
# 检查容器状态
docker compose ps
# 检查容器健康状态
docker inspect --format='{{.State.Health.Status}}' math_cms_app
docker inspect --format='{{.State.Health.Status}}' math_cms_queue
docker inspect --format='{{.State.Health.Status}}' math_cms_pdf
# 检查 PHP-FPM 进程数
docker exec math_cms_app ps aux | grep php-fpm | wc -l
# 检查 Nginx Worker 数
docker exec math_cms_app ps aux | grep nginx
# 备份日志
cp -r storage/logs storage/logs_backup_$(date +%Y%m%d)
# 备份上传文件
cp -r storage/app/public storage/app/public_backup_$(date +%Y%m%d)
# 清理临时文件(每小时)
0 * * * * cd /path/to/math_cms && rm -rf storage/app/temp/* 2>/dev/null
# 清理旧日志(每天凌晨 3 点)
0 3 * * * find /path/to/math_cms/storage/logs -name "*.log" -mtime +7 -delete
# 查看资源限制
docker inspect math_cms_pdf --format='{{.HostConfig.Memory}}'
# 临时调整资源限制
docker update --cpus=1 --memory=1g math_cms_pdf
┌──────────────────────────────────────────────────────────────────┐
│ Docker Compose │
│ ┌──────────────────┐ ┌───────────────┐ ┌──────────────────────┐ │
│ │ math_cms_app │ │ math_cms_queue│ │ math_cms_pdf │ │
│ │ (Nginx+PHP-FPM) │ │ (Queue Worker)│ │ (PDF Worker) │ │
│ │ :5019 → :8000 │ │ default 队列 │ │ pdf 队列 │
│ │ 并发: 30 worker │ │ CPU:1 Mem:512M│ │ CPU:2 Mem:2G │ │
│ └──────────────────┘ └───────────────┘ └──────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
│ │ │
└─────────────────────┴─────────────────────┘
│
┌──────────────────┴──────────────────┐
▼ ▼
┌──────────┐ ┌──────────┐
│ Redis │ │ MySQL │
│ (阿里云) │ │ (阿里云) │
└──────────┘ └──────────┘
| 队列 | 容器 | 处理任务 |
|---|---|---|
| default | math_cms_queue | AI批改、知识点匹配、题目导入等 |
| math_cms_pdf | PDF生成(需要Chrome) |
问题1: PDF生成超时(50秒后失败)
问题2: 公式显示为原始 LaTeX 文本
问题3: dbus 连接错误
Failed to connect to the bus 错误问题4: Chrome 进程积累导致 CPU 满载
解决:
# 强制清理Chrome进程
docker exec math_cms_pdf pkill -9 chromium
# 清理临时文件
docker exec math_cms_pdf rm -rf /tmp/chrome-profile-* /tmp/exam_*
# 重启PDF服务
docker compose restart pdf-worker
问题5: 日志为空(权限问题)
解决:
docker exec math_cms_app chmod -R 777 /app/storage
问题6: GenerateAnalysisPdfJob 失败
$this->onQueue('pdf')# 查看PDF生成日志
docker exec math_cms_app grep -i "ExamPdfExportService" storage/logs/laravel.log | tail -50
# 查看KaTeX渲染日志
docker exec math_cms_app grep -i "KatexRenderer\|LaTeX.*预渲染" storage/logs/laravel.log | tail -20
# 测试Node.js KaTeX是否正常工作
docker exec math_cms_app sh -c "echo '\$x^2 + y^2 = z^2\$' | node /app/scripts/katex-render.mjs"
# 测试Chrome是否正常工作
docker exec math_cms_pdf chromium-browser --headless --disable-gpu --no-sandbox --print-to-pdf=/tmp/test.pdf https://www.baidu.com
# 检查Chrome版本
docker exec math_cms_pdf chromium-browser --version
# 检查Node.js版本
docker exec math_cms_app node --version
# 检查dbus状态
docker exec math_cms_pdf pgrep -a dbus
# 查看 PDF 队列处理情况
docker logs math_cms_pdf --tail=30
错误信息:题目插入数量不匹配:预期 20,实际 40
原因: 并发请求导致 Paper ID 碰撞,两个请求插入到同一个 paper_id
解决: 已优化 PaperIdGenerator,增加进程ID区分不同 PHP-FPM Worker
排查命令:
# 查看相关错误
docker exec math_cms_app grep "题目插入数量不匹配" storage/logs/laravel.log | tail -10
如有问题请联系开发团队。