#!/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