适用:内网 / 家庭 / 小团队(≤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 上部署时跑一遍文档步骤即可。
219 lines
5.2 KiB
Markdown
219 lines
5.2 KiB
Markdown
# 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
|
||
# 编辑 .env:SECRET_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 并发的场景完全够用。 |