Files
pear-admin-flask/docs/deployment-nas.md
T
bwstudio 98edfdaf2d feat(deploy): 个人 NAS 单机 Docker 部署方案
适用:内网 / 家庭 / 小团队(≤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 上部署时跑一遍文档步骤即可。
2026-09-06 18:35:31 +08:00

219 lines
5.2 KiB
Markdown
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.
# Pear Admin Flask - 个人 NAS 部署指南
适用:内网 / 家庭 / 小团队(≤ 50 并发用户,无 K8s 需求)。
---
## 1. 前置检查
NAS 上需安装:
| 软件 | 最低版本 | 验证命令 |
|---|---|---|
| Docker Engine | 20.10+ | `docker --version` |
| Docker Compose | v2.x | `docker compose version` |
> 如果 NAS 是群晖 / 威联通,请在套件中心安装 **Container Manager** 或自行 SSH 安装 docker。
---
## 2. 准备 .env
```bash
cd /path/to/pear-admin-flask
cp .env.example .env
# 编辑 .envSECRET_KEY 必须改成强随机字符串
python -c "import secrets; print(secrets.token_urlsafe(48))"
# 把输出贴到 .env 的 SECRET_KEY=
```
`.env` **绝不能提交到 git**(已在 `.gitignore` 中)。
---
## 3. 首次构建 + 启动
```bash
# 进入项目目录
cd /volume1/docker/pear-admin-flask # 改成你自己的路径
# 构建镜像(首次约 3-5 分钟)
docker compose -f deploy/nas/docker-compose.yaml build
# 后台启动
docker compose -f deploy/nas/docker-compose.yaml up -d
# 查看启动日志(应看到 "Listening at: http://0.0.0.0:5000"
docker compose -f deploy/nas/docker-compose.yaml logs -f
```
启动成功后访问:`http://NAS_IP:5000`
默认账号 `admin` / `123456`(首次登录后**强烈建议改密码**)。
---
## 4. 健康检查
```bash
# 进程是否还活着(DB OK 返回 200;DB 不可达返回 503)
curl -i http://NAS_IP:5000/healthz
# 200 OK: {"status":"ok","db_ok":true,"env":"production","system":"Pear Admin","timestamp":"..."}
# 容器视角的健康状态(Docker 30s 探一次)
docker inspect --format='{{.State.Health.Status}}' pear-admin-nas
# healthy / unhealthy / starting
```
---
## 5. 端口与局域网访问
`docker-compose.yaml` 中默认 `5000:5000`,局域网内任意设备 `http://NAS_IP:5000` 都能访问。
如要改端口(如 NAS 上 5000 被占用):
```yaml
ports:
- "8080:5000" # 宿主 8080 → 容器 5000
```
手机访问:`http://NAS_IP:8080`(确保 NAS 防火墙放行)。
---
## 6. 数据持久化
| 卷名 | 容器内路径 | 内容 |
|---|---|---|
| `pear-admin-nas_pear_db` | `/app/pear.db` | SQLite 数据库 |
| `pear-admin-nas_logs` | `/app/logs` | gunicorn / Flask 日志 |
| `pear-admin-nas_session` | `/app/flask_session` | 登录会话文件 |
| `pear-admin-nas_upload` | `/app/static/upload` | 上传图片 |
查看卷:
```bash
docker volume ls | grep pear
```
### 备份 SQLite 数据库
```bash
# 备份(推荐每天 1 次,可加入 cron)
docker run --rm \
-v pear-admin-nas_pear_db:/data \
-v /volume1/docker/pear-backup:/backup \
alpine sh -c "cp /data/pear.db /backup/pear-$(date +%F).db && ls -la /backup/"
```
恢复:
```bash
docker compose -f deploy/nas/docker-compose.yaml down
docker run --rm \
-v pear-admin-nas_pear_db:/data \
-v /volume1/docker/pear-backup:/backup \
alpine sh -c "rm -f /data/pear.db && cp /backup/pear-2026-09-06.db /data/pear.db"
docker compose -f deploy/nas/docker-compose.yaml up -d
```
---
## 7. 升级流程
```bash
# 1. 拉取最新代码
cd /volume1/docker/pear-admin-flask
git pull
# 2. 重新构建镜像
docker compose -f deploy/nas/docker-compose.yaml build
# 3. 重启容器(migrations 自动跑)
docker compose -f deploy/nas/docker-compose.yaml up -d
# 4. 验证
curl -i http://NAS_IP:5000/healthz
```
数据库迁移由 `start.sh` 中的 `flask db upgrade` 自动执行(幂等)。
---
## 8. 常见问题
### Q1:容器启动后立刻退出
```bash
docker compose -f deploy/nas/docker-compose.yaml logs --tail=50
```
最常见原因:
- `SECRET_KEY` 还是占位符 `PLEASE_REPLACE_WITH_RANDOM_STRING` → ProConfig 会拒绝启动
- 端口被占用 → 修改 `ports`
### Q2:访问首页 502 / 拒绝连接
```bash
# 确认容器在跑
docker ps | grep pear-admin-nas
# 看健康状态
docker inspect --format='{{.State.Health.Status}}' pear-admin-nas
```
### Q3:忘记 admin 密码
直接重置(删容器、再用空 pear.db 启动,再 `flask admin init` 重新生成默认账号):
```bash
docker compose -f deploy/nas/docker-compose.yaml down
docker volume rm pear-admin-nas_pear_db
docker compose -f deploy/nas/docker-compose.yaml up -d
```
⚠️ **此操作会清空所有数据**,务必先备份。
### Q4:日志占满磁盘
```bash
# 查看日志大小
docker system df -v
# 清理已停止容器的日志
docker compose -f deploy/nas/docker-compose.yaml down
docker volume rm pear-admin-nas_logs
docker compose -f deploy/nas/docker-compose.yaml up -d
```
### Q5:想要外网访问
需要做两件事:
1. NAS 上做端口映射(5000 → 公网 IP + DDNS
2. **必须**在前面套一层 Nginx/Caddy 加 HTTPS(避免密码明文)
可参考 `deploy/nas/README.md`(如果后续加入 nginx 反代方案)。
---
## 9. 性能调优
NAS 通常内存有限(4-8 GB)。如遇卡顿:
```yaml
# docker-compose.yaml 中调小资源限制
deploy:
resources:
limits:
memory: 768M # 从 1024M 降到 768M
```
或减少 worker
```yaml
environment:
- GUNICORN_WORKERS=1 # 内存紧张时降到 1
```
Gunicorn 默认 `2 workers × 4 threads = 8 个并发槽位**,对 ≤ 50 并发的场景完全够用。