add temporary deploy
This commit is contained in:
@@ -10,7 +10,17 @@
|
||||
- pytest / FastAPI TestClient
|
||||
- Docker / Docker Compose
|
||||
|
||||
项目目标是小而稳、容易继续扩展。目前已经支持固定三层的数据结构、基础 CRUD、单图上传能力和全局搜索,但仍然没有加入 OCR、AI 识别或其他扩展功能。
|
||||
项目目标是小而稳、容易继续扩展。它不是企业平台,也不是复杂运维系统,重点是本地开发简单、容器部署稳定、数据持久化清楚、后续几个月后自己回来看也能快速接上。
|
||||
|
||||
## 当前已支持
|
||||
|
||||
- 固定 3 级结构:`Box -> Item -> SubItem`
|
||||
- Box / Item / SubItem 基础 CRUD
|
||||
- Box / Item / SubItem 单图上传、替换、删除、展示
|
||||
- Box / Item / SubItem 全局搜索
|
||||
- Docker / Compose 长期运行
|
||||
- SQLite 数据持久化
|
||||
- 基础自动化测试
|
||||
|
||||
## 当前数据模型
|
||||
|
||||
@@ -36,30 +46,9 @@ Box
|
||||
└── SubItem
|
||||
```
|
||||
|
||||
## 当前已支持
|
||||
|
||||
目前已支持的基础能力:
|
||||
|
||||
- Box 列表、详情、新建、编辑、删除
|
||||
- Item 新建、详情、编辑、删除
|
||||
- SubItem 新建、编辑、删除
|
||||
- Box / Item / SubItem 单张图片上传、替换、删除、展示
|
||||
- Box / Item / SubItem 全局搜索
|
||||
- `/` 重定向到 `/boxes`
|
||||
- Jinja2 模板渲染
|
||||
- 静态文件挂载
|
||||
- SQLite 持久化
|
||||
- Docker 长期运行
|
||||
- 基础自动化测试
|
||||
|
||||
删除规则:
|
||||
|
||||
- 删除 `Box` 时,会级联删除其下全部 `Item` 和对应 `SubItem`
|
||||
- 删除容器型 `Item` 时,会级联删除其下 `SubItem`
|
||||
|
||||
## 图片能力说明
|
||||
|
||||
这一阶段的图片系统保持简单直接:
|
||||
图片系统保持简单直接:
|
||||
|
||||
- `Box` 最多支持 1 张图片
|
||||
- `Item` 最多支持 1 张图片
|
||||
@@ -67,10 +56,7 @@ Box
|
||||
- 支持上传、替换、删除
|
||||
- 不支持多图
|
||||
|
||||
图片的主要用途是帮助识别物品、提高浏览效率、方便手机拍照后直接附加到记录中。
|
||||
它不是一个原图归档系统。
|
||||
|
||||
### 图片处理方式
|
||||
图片主要用于帮助识别物品、提高浏览效率、方便手机拍照后直接附加到记录中。它不是原图归档系统。
|
||||
|
||||
上传图片后,系统会使用 Pillow 做统一处理:
|
||||
|
||||
@@ -87,7 +73,7 @@ Box
|
||||
- `image_width`
|
||||
- `image_height`
|
||||
|
||||
图片访问通过普通 HTTP 路由返回 JPEG 数据,例如:
|
||||
图片访问路由例如:
|
||||
|
||||
- `/boxes/{id}/image`
|
||||
- `/items/{id}/image`
|
||||
@@ -95,10 +81,10 @@ Box
|
||||
|
||||
## 全局搜索
|
||||
|
||||
当前已经支持一个轻量的全局搜索页:
|
||||
当前支持一个轻量的全局搜索页:
|
||||
|
||||
- 路由:`/search`
|
||||
- 使用 query parameter,例如:`/search?q=电源线`
|
||||
- 方式:`GET /search?q=关键词`
|
||||
|
||||
搜索范围包括:
|
||||
|
||||
@@ -109,13 +95,13 @@ Box
|
||||
- `SubItem.name`
|
||||
- `SubItem.note`
|
||||
|
||||
当前使用 SQLite 上的简单模糊匹配完成搜索,不引入外部搜索引擎或复杂全文系统。
|
||||
当前使用 SQLite 上的简单模糊匹配,不引入外部搜索引擎或复杂全文系统。
|
||||
|
||||
搜索结果会尽量帮助你快速定位:
|
||||
搜索结果会显示:
|
||||
|
||||
- 显示对象类型:`Box / Item / SubItem`
|
||||
- 显示名称和备注
|
||||
- 显示归属路径
|
||||
- 对象类型:`Box / Item / SubItem`
|
||||
- 名称和备注
|
||||
- 归属路径
|
||||
- 对 `Item` 展示所属 `Box`
|
||||
- 对 `SubItem` 展示所属 `Item` 和 `Box`
|
||||
- 如果对象已有图片,会显示一个小缩略图
|
||||
@@ -124,7 +110,6 @@ Box
|
||||
|
||||
这一阶段仍然没有实现以下内容:
|
||||
|
||||
- 搜索
|
||||
- 多图上传
|
||||
- OCR
|
||||
- AI 识别物品
|
||||
@@ -149,14 +134,13 @@ Box
|
||||
│ ├── static
|
||||
│ │ └── style.css
|
||||
│ └── templates
|
||||
│ ├── base.html
|
||||
│ ├── boxes
|
||||
│ ├── items
|
||||
│ └── subitems
|
||||
├── data
|
||||
├── scripts
|
||||
│ ├── backup_db.sh
|
||||
│ └── deploy.sh
|
||||
├── tests
|
||||
│ ├── conftest.py
|
||||
│ └── test_app.py
|
||||
├── .dockerignore
|
||||
├── .env.example
|
||||
├── docker-compose.yml
|
||||
├── Dockerfile
|
||||
├── pytest.ini
|
||||
@@ -166,17 +150,38 @@ Box
|
||||
|
||||
## 轻量配置
|
||||
|
||||
项目通过环境变量支持以下配置项:
|
||||
项目通过环境变量支持以下部署时真正需要关心的配置:
|
||||
|
||||
- `DATABASE_URL`
|
||||
- `HOST`
|
||||
- `PORT`
|
||||
- `DATABASE_URL`
|
||||
- `DATA_DIR`
|
||||
- `UID`
|
||||
- `GID`
|
||||
|
||||
默认值:
|
||||
推荐从示例文件开始:
|
||||
|
||||
- `DATABASE_URL=sqlite:///./data/app.db`
|
||||
- `HOST=0.0.0.0`
|
||||
- `PORT=10000`
|
||||
```bash
|
||||
cp .env.example .env
|
||||
```
|
||||
|
||||
默认值如下:
|
||||
|
||||
```env
|
||||
HOST=0.0.0.0
|
||||
PORT=10000
|
||||
DATABASE_URL=sqlite:////app/data/app.db
|
||||
DATA_DIR=./data
|
||||
UID=1000
|
||||
GID=1000
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 本地开发默认数据库仍然是 `./data/app.db`
|
||||
- Docker 内建议继续使用 `sqlite:////app/data/app.db`
|
||||
- `DATA_DIR` 控制宿主机上的持久化目录
|
||||
- `UID/GID` 用来让容器内文件权限更贴近宿主机用户
|
||||
|
||||
## 本地开发模式
|
||||
|
||||
@@ -213,14 +218,33 @@ http://localhost:10000
|
||||
./data/app.db
|
||||
```
|
||||
|
||||
## Docker 部署模式
|
||||
## Docker 运行方式
|
||||
|
||||
Docker / Compose 是这个项目面向长期运行环境的方式。
|
||||
|
||||
启动:
|
||||
### 首次准备
|
||||
|
||||
```bash
|
||||
docker compose up --build
|
||||
cp .env.example .env
|
||||
mkdir -p data
|
||||
```
|
||||
|
||||
### 启动 / 更新
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
### 查看状态
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
docker compose logs -f web
|
||||
```
|
||||
|
||||
访问:
|
||||
@@ -229,20 +253,129 @@ docker compose up --build
|
||||
http://localhost:10000
|
||||
```
|
||||
|
||||
说明:
|
||||
### Compose 配置说明
|
||||
|
||||
当前 `docker-compose.yml` 保持尽量简单:
|
||||
|
||||
- 默认暴露 `10000` 端口
|
||||
- `restart: unless-stopped`
|
||||
- 容器使用 `1000:1000` 运行
|
||||
- SQLite 文件持久化到宿主机 `./data/app.db`
|
||||
- 容器重建不会丢失数据
|
||||
- 容器用户来自 `UID:GID`
|
||||
- 宿主机 `DATA_DIR` 挂载到容器内 `/app/data`
|
||||
- SQLite 默认写入 `/app/data/app.db`
|
||||
|
||||
备份时直接复制 SQLite 文件即可:
|
||||
## 自动化部署
|
||||
|
||||
这个项目没有复杂 CI/CD,只提供一个适合家用项目的轻量部署脚本:
|
||||
|
||||
```bash
|
||||
./scripts/deploy.sh
|
||||
```
|
||||
|
||||
它会按顺序执行:
|
||||
|
||||
1. 检查 `.env`
|
||||
2. 准备数据目录
|
||||
3. 如果当前目录是 git 仓库,执行 `git pull --ff-only`
|
||||
4. 执行 `docker compose up -d --build`
|
||||
5. 输出容器状态
|
||||
6. 输出最近日志
|
||||
|
||||
这个脚本的目标不是做平台化发布,而是让“更新代码并刷新容器”变成一个稳定、可重复执行的动作。
|
||||
|
||||
如果你不想自动拉代码,也可以直接手动运行:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## 数据持久化
|
||||
|
||||
当前 SQLite 文件默认会保存在:
|
||||
|
||||
- 宿主机:`./data/app.db`
|
||||
- 容器内:`/app/data/app.db`
|
||||
|
||||
这是因为 `docker-compose.yml` 把:
|
||||
|
||||
```text
|
||||
./data/app.db
|
||||
${DATA_DIR:-./data}
|
||||
```
|
||||
|
||||
挂载到了容器内:
|
||||
|
||||
```text
|
||||
/app/data
|
||||
```
|
||||
|
||||
因此:
|
||||
|
||||
- 容器重建不会删除宿主机上的数据库文件
|
||||
- 更新镜像不会导致 SQLite 数据丢失
|
||||
- 只要保留 `DATA_DIR` 目录,数据就还在
|
||||
|
||||
## 备份与恢复
|
||||
|
||||
### 最简单的备份方式
|
||||
|
||||
直接复制 SQLite 文件即可:
|
||||
|
||||
```bash
|
||||
cp data/app.db backups/app.db
|
||||
```
|
||||
|
||||
或者使用附带脚本:
|
||||
|
||||
```bash
|
||||
./scripts/backup_db.sh
|
||||
```
|
||||
|
||||
它会在 `backups/` 目录下生成一个带时间戳的副本。
|
||||
|
||||
### 最简单的恢复方式
|
||||
|
||||
停止容器后,把备份文件覆盖回去:
|
||||
|
||||
```bash
|
||||
docker compose stop
|
||||
cp backups/app-YYYYMMDD-HHMMSS.db data/app.db
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 常见排查
|
||||
|
||||
### 1. 查看容器日志
|
||||
|
||||
```bash
|
||||
docker compose logs -f web
|
||||
```
|
||||
|
||||
### 2. 确认服务是否已启动
|
||||
|
||||
```bash
|
||||
docker compose ps
|
||||
```
|
||||
|
||||
如果状态是 `Up`,通常说明容器已经跑起来了。
|
||||
|
||||
### 3. 确认端口映射
|
||||
|
||||
```bash
|
||||
docker compose port web 10000
|
||||
```
|
||||
|
||||
### 4. 确认数据库文件还在
|
||||
|
||||
```bash
|
||||
ls -lh data
|
||||
```
|
||||
|
||||
如果看到 `app.db`,说明宿主机持久化文件还在。
|
||||
|
||||
### 5. 容器更新后数据为什么没丢
|
||||
|
||||
因为数据库不放在镜像里,而是放在宿主机挂载目录 `DATA_DIR` 中。
|
||||
镜像更新只会替换应用代码和运行环境,不会覆盖这个宿主机目录。
|
||||
|
||||
## 测试
|
||||
|
||||
运行测试:
|
||||
@@ -256,10 +389,7 @@ python -m pytest
|
||||
当前测试覆盖包括:
|
||||
|
||||
- Box / Item / SubItem 基础 CRUD
|
||||
- 404 返回
|
||||
- 非容器 Item 不能创建 SubItem
|
||||
- Box / Item 删除后的级联删除
|
||||
- 图片上传、转换为 JPEG、缩放、读取、替换、删除
|
||||
- 全局搜索 name / note,并展示对象类型与归属路径
|
||||
- 无图片访问和非法图片上传等错误路径
|
||||
- 关键 POST 请求后的重定向行为
|
||||
- 图片上传、替换、删除与错误路径
|
||||
- 全局搜索 name / note
|
||||
- 创建后的重定向行为
|
||||
- 关键页面结构和 UX 文案
|
||||
|
||||
Reference in New Issue
Block a user