- 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 流程)
61 lines
2.1 KiB
Docker
61 lines
2.1 KiB
Docker
# =====================================================
|
||
# Pear Admin Flask - 个人 NAS / 单机部署 Dockerfile
|
||
# =====================================================
|
||
# 适用场景:内网访问 / 少量并发 / 数据量小
|
||
# 基础:python:3.11-slim(~150 MB),无 MySQL,纯 SQLite
|
||
#
|
||
# 构建: docker build -f deploy/nas/Dockerfile -t pear-admin-nas .
|
||
# 运行: docker compose -f deploy/nas/docker-compose.yaml up -d
|
||
# =====================================================
|
||
|
||
FROM python:3.11-slim
|
||
|
||
# 容器内时区与 Python 输出
|
||
ENV TZ=Asia/Shanghai \
|
||
PYTHONUNBUFFERED=1 \
|
||
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
||
PIP_NO_CACHE_DIR=1 \
|
||
PEAR_ENV=pro \
|
||
PEAR_DATA_DIR=/app/data \
|
||
FLASK_APP=app.py
|
||
|
||
# 安装时区数据 + 健康检查用的 curl
|
||
# (curl 在 slim 里已有,但保持显式声明便于以后切到 alpine)
|
||
RUN apt-get update \
|
||
&& apt-get install -y --no-install-recommends curl tzdata sqlite3 \
|
||
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
|
||
&& echo $TZ > /etc/timezone \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
|
||
# 非 root 运行(生产最佳实践)
|
||
RUN useradd -m -u 1001 appuser
|
||
|
||
WORKDIR /app
|
||
|
||
# 先只 copy 依赖文件 → 利用 Docker 缓存;requirements 不变则跳过 pip install
|
||
COPY requirements.txt ./
|
||
RUN pip install -r requirements.txt \
|
||
&& pip install gunicorn==21.2.0
|
||
|
||
# 再 copy 全部源码
|
||
COPY --chown=appuser:appuser . .
|
||
|
||
# 数据目录单独建好并 chown 给 appuser(uid 1001)。
|
||
# /app/data 由卷挂载覆盖,但容器刚启动时如果宿主目录是空的,
|
||
# 子目录(backup/ flask_session/ 等)需要 appuser 自己能写。
|
||
RUN mkdir -p /app/data/backup /app/data/flask_session /app/data/logs /app/data/upload \
|
||
&& chown -R appuser:appuser /app/data
|
||
|
||
# 启动脚本加执行权限
|
||
RUN chmod +x /app/deploy/nas/start.sh /app/deploy/nas/backup.sh
|
||
|
||
# 切换到非 root
|
||
USER appuser
|
||
|
||
EXPOSE 5000
|
||
|
||
# 容器健康检查:访问 /healthz 接口(applications/view/health.py 提供,DB 不可达返回 503)
|
||
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||
CMD curl -fsS http://localhost:5000/healthz || exit 1
|
||
|
||
CMD ["/app/deploy/nas/start.sh"] |