Files
pear-admin-flask/deploy/nas/start.sh
T
bwstudio be99b8a925 feat(data): 数据库搬到 data/ 目录 + SQLite WAL + 单卷绑定挂载
- config.py 新增 PEAR_DATA_DIR(默认 <项目根>/data),SQLite 库、Flask-Session
  统一收进 DATA_DIR;不设时本地开发行为不变
- applications/__init__.py 顶部先 load_dotenv,保证 .env 里的 PEAR_DATA_DIR
  在 config 导入时就生效
- extensions/init_sqlalchemy.py 接 SQLite connect 事件:WAL + synchronous=NORMAL
  + busy_timeout=30s(多 worker 写不再撞锁)
- config.py 注入 SQLALCHEMY_ENGINE_OPTIONS(pool_pre_ping + SQLite connect_args
  超时;MySQL 路径下自动跳过 connect_args 防止参数错误)
- 新增 alembic 迁移 a47a5d2a3f1b 建 site_nav_click(含 anon_id 字段),
  解决之前该表只由 db.create_all 建、不在迁移链里的隐患
- .gitignore / .dockerignore 加 data/ 排除规则(且把 migrations/ 从
  ignore 里重新放行 —— 否则新加的迁移进不了库)
- NAS Docker 部署全面重写:
  - compose 唯一绑定挂载 ./data:/app/data,宿主 File Station 看得见
  - start.sh 自检 data 目录 + 子目录;workers 默认改为 1 threads 8
    (SQLite 写串行,单进程最稳)
  - 新增 backup.sh:sqlite3 .backup 在线热备(确保 WAL 一致性)+ 压缩
    + 保留 14 天
  - Dockerfile 安装 sqlite3 客户端备用,建 /app/data 子目录并 chown
- docs/deployment-nas.md 重写数据持久化章节(路径表 + 热备命令 +
  恢复步骤 + 整库迁移 tar/untar 流程)
2026-09-06 19:43:28 +08:00

58 lines
2.3 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Pear Admin Flask - NAS 生产启动脚本
#
# 流程:
# 1. 数据目录检查:PEAR_DATA_DIR 必须存在且可写;不存在则用默认行为
# 2. alembic 迁移到最新版本(幂等;migrations 文件夹随镜像打包)
# 3. flask admin init 幂等初始化菜单/权限(已有则跳过)
# 4. exec 切换到 gunicornPID 1 由 gunicorn 接管
#
# 注意:必须 exec,否则容器启动后 PID 1 是 shell 而非 gunicorn
# docker stop 发出的 SIGTERM 不会被正确转发,graceful shutdown 失效。
set -e
DATA_DIR=${PEAR_DATA_DIR:-/app/data}
echo "=== [1/4] 数据目录 ==="
echo "PEAR_DATA_DIR=${DATA_DIR}"
mkdir -p "${DATA_DIR}/backup" "${DATA_DIR}/flask_session" "${DATA_DIR}/logs" "${DATA_DIR}/upload"
# 确保子目录可写(WAL 模式下 SQLite 需要 pear.db 同目录的 -wal / -shm 也能创建)
touch "${DATA_DIR}/.write_test" && rm -f "${DATA_DIR}/.write_test" || {
echo "FATAL: data dir not writable: ${DATA_DIR}" >&2
exit 1
}
echo "=== [2/4] 等待数据库就绪 ==="
# 默认 SQLite 不需要等待;这里预留扩展位(如未来切 MySQL,可在此加 wait-for-it
if [[ "${SQLALCHEMY_DATABASE_URI:-}" == mysql* ]]; then
echo "检测到 MySQL,等待 10s 让 db 服务启动..."
sleep 10
fi
echo "=== [3/4] 初始化数据库(幂等) ==="
# flask 命令依赖 FLASK_APP;镜像里已经设过;这里再 fallback 一次
export FLASK_APP=${FLASK_APP:-app.py}
# 数据库迁移:migrate 仅当模型有变才生成新版本;upgrade 永远是幂等的
flask db upgrade || echo "WARN: flask db upgrade failed (首次启动可能正常)"
flask admin init || true
echo "=== [4/4] 启动 Gunicorn ==="
# SQLite + WAL 模式下,多 worker 写文件本身没问题(同时间互不阻塞),
# 但多个事务并发提交仍可能撞锁。这里把 worker 降到 1(线程给够),
# 既能吃满并发量、又把"database is locked"概率压到最低。
WORKERS=${GUNICORN_WORKERS:-1}
THREADS=${GUNICORN_THREADS:-8}
TIMEOUT=60
exec gunicorn \
--bind 0.0.0.0:5000 \
--workers "$WORKERS" \
--threads "$THREADS" \
--timeout "$TIMEOUT" \
--graceful-timeout 30 \
--keep-alive 5 \
--access-logfile "${DATA_DIR}/logs/access.log" \
--error-logfile "${DATA_DIR}/logs/error.log" \
--log-level info \
app:app