适用:内网 / 家庭 / 小团队(≤50 并发),无 K8s 需求。
特性:单容器 + SQLite + 端口暴露,最小维护成本。
新增:
- deploy/nas/Dockerfile: python:3.11-slim 基础镜像 + 非 root + HEALTHCHECK
- deploy/nas/start.sh: flask db upgrade 幂等迁移 + gunicorn (2 workers × 4 threads)
- deploy/nas/docker-compose.yaml: 单服务 + 4 个命名卷 (db/logs/session/upload) + 资源限制
- docs/deployment-nas.md: 完整部署/备份/升级/排障指南
完善:
- .env.example: 改为生产环境导向 (PEAR_ENV=pro,SECRET_KEY 必填)
- .dockerignore: 排除 deploy/dev (开发用容器配置)、tests/截图、一次性脚本
- applications/view/public/__init__.py: 注释说明 /healthz 已在 applications/view/health.py 注册
复用现有:
- /healthz 接口 (applications/view/health.py) 含 DB 探活,DB 不可达返回 503
→ 容器 HEALTHCHECK 直接用 /healthz 即可
⚠️ 本机无 docker,未执行 docker build 验证;已静态校验 YAML/bash 语法、
文件路径、.env 字段消费、ProConfig 严格性、/healthz 端点可用性。
首次 NAS 上部署时跑一遍文档步骤即可。
45 lines
1.5 KiB
Bash
45 lines
1.5 KiB
Bash
#!/bin/bash
|
||
# Pear Admin Flask - NAS 生产启动脚本
|
||
#
|
||
# 流程:
|
||
# 1. alembic 迁移到最新版本(幂等;migrations 文件夹随镜像打包)
|
||
# 2. flask admin init 幂等初始化菜单/权限(已有则跳过)
|
||
# 3. exec 切换到 gunicorn,PID 1 由 gunicorn 接管
|
||
#
|
||
# 注意:必须 exec,否则容器启动后 PID 1 是 shell 而非 gunicorn,
|
||
# docker stop 发出的 SIGTERM 不会被正确转发,graceful shutdown 失效。
|
||
|
||
set -e
|
||
|
||
echo "=== [1/3] 等待数据库就绪 ==="
|
||
# SQLite 不需要等待;这里预留扩展位(如未来切 MySQL,可在此加 wait-for-it)
|
||
if [[ "${SQLALCHEMY_DATABASE_URI:-}" == mysql* ]]; then
|
||
echo "检测到 MySQL,等待 10s 让 db 服务启动..."
|
||
sleep 10
|
||
fi
|
||
|
||
echo "=== [2/3] 初始化数据库(幂等) ==="
|
||
# 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 "=== [3/3] 启动 Gunicorn ==="
|
||
# worker 数:NAS 单容器 2-4 足够;线程 4 让 4 类 IO 密集(埋点/统计)能并发
|
||
WORKERS=${GUNICORN_WORKERS:-2}
|
||
THREADS=4
|
||
TIMEOUT=60
|
||
|
||
exec gunicorn \
|
||
--bind 0.0.0.0:5000 \
|
||
--workers "$WORKERS" \
|
||
--threads "$THREADS" \
|
||
--timeout "$TIMEOUT" \
|
||
--graceful-timeout 30 \
|
||
--keep-alive 5 \
|
||
--access-logfile - \
|
||
--error-logfile - \
|
||
--log-level info \
|
||
app:app |