新增自动构建镜像
This commit is contained in:
parent
37581e7b4d
commit
16d9946c25
137
README.md
137
README.md
@ -184,10 +184,12 @@ xianyu-auto-reply/
|
||||
│ ├── .gitignore # Git忽略文件配置(完整版)
|
||||
│ └── README.md # 项目说明文档(本文件)
|
||||
└── 📊 数据目录(运行时创建)
|
||||
├── data/ # 数据目录(Docker挂载)
|
||||
│ └── xianyu_data.db # SQLite数据库文件
|
||||
├── data/ # 数据目录(Docker挂载,自动创建)
|
||||
│ ├── xianyu_data.db # SQLite主数据库文件
|
||||
│ ├── user_stats.db # 用户统计数据库
|
||||
│ └── xianyu_data_backup_*.db # 数据库备份文件
|
||||
├── logs/ # 按日期分割的日志文件
|
||||
└── backups/ # 数据备份文件
|
||||
└── backups/ # 其他备份文件
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -203,6 +205,12 @@ xianyu-auto-reply/
|
||||
- ✅ 完善的错误处理和重试机制,提升系统稳定性
|
||||
- ✅ 修复滑块验证模块内存泄漏问题,浏览器资源正确释放
|
||||
|
||||
**📦 数据管理优化**
|
||||
- ✅ 数据库文件统一迁移到 `data/` 目录,更好的组织和管理
|
||||
- ✅ 启动时自动检测并迁移旧数据库文件,无需手动操作
|
||||
- ✅ 备份文件自动整理到数据目录,便于集中管理
|
||||
- ✅ Docker挂载更简洁,一个data目录包含所有数据
|
||||
|
||||
**🛠️ 配置文件优化**
|
||||
- ✅ 完善 `.gitignore`,新增编译产物、浏览器缓存等规则
|
||||
- ✅ 完善 `.dockerignore`,优化Docker构建速度和镜像体积
|
||||
@ -221,9 +229,10 @@ xianyu-auto-reply/
|
||||
|
||||
**🏗️ 多架构支持**
|
||||
- ✅ Docker镜像支持AMD64和ARM64双架构
|
||||
- ✅ GitHub Actions自动构建多架构镜像
|
||||
- ✅ GitHub Actions自动构建并推送到双镜像仓库
|
||||
- ✅ 支持Oracle Cloud、AWS Graviton等ARM服务器
|
||||
- ✅ Docker自动选择匹配的架构,无需手动指定
|
||||
- ✅ 国内外双镜像源,确保下载速度
|
||||
|
||||
## 🚀 云服务器推荐
|
||||
|
||||
@ -234,26 +243,57 @@ xianyu-auto-reply/
|
||||
|
||||
**⚡ 最快部署方式(推荐)**:使用预构建镜像,无需下载源码,一条命令即可启动!
|
||||
|
||||
### 方式一:Docker 一键部署(最简单)
|
||||
### 方式一:Docker 一键部署(最简单)⭐
|
||||
|
||||
**国内用户(阿里云镜像,推荐)**:
|
||||
```bash
|
||||
# 1. 创建数据目录
|
||||
mkdir -p xianyu-auto-reply
|
||||
|
||||
# 2. 一键启动容器
|
||||
docker run -d -p 8080:8080 --restart always -v $PWD/xianyu-auto-reply/:/app/data/ --name xianyu-auto-reply registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:1.0.4
|
||||
# 2. 一键启动容器(支持AMD64/ARM64,自动选择架构)
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
--restart always \
|
||||
-v $PWD/xianyu-auto-reply/:/app/data/ \
|
||||
--name xianyu-auto-reply \
|
||||
registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest
|
||||
|
||||
# 3. 访问系统
|
||||
# http://localhost:8080
|
||||
```
|
||||
|
||||
**国际用户(Docker Hub镜像)**:
|
||||
```bash
|
||||
# 使用Docker Hub国际镜像
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
--restart always \
|
||||
-v $PWD/xianyu-auto-reply/:/app/data/ \
|
||||
--name xianyu-auto-reply \
|
||||
zhinianblog/xianyu-auto-reply:latest
|
||||
```
|
||||
|
||||
**Windows用户**:
|
||||
```cmd
|
||||
```powershell
|
||||
# 创建数据目录
|
||||
mkdir xianyu-auto-reply
|
||||
|
||||
# 启动容器
|
||||
docker run -d -p 8080:8080 -v %cd%/xianyu-auto-reply/:/app/data/ --name xianyu-auto-reply registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:1.0.4
|
||||
# 国内用户(阿里云)
|
||||
docker run -d -p 8080:8080 --restart always -v %cd%/xianyu-auto-reply/:/app/data/ --name xianyu-auto-reply registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest
|
||||
|
||||
# 国际用户(Docker Hub)
|
||||
docker run -d -p 8080:8080 --restart always -v %cd%/xianyu-auto-reply/:/app/data/ --name xianyu-auto-reply zhinianblog/xianyu-auto-reply:latest
|
||||
```
|
||||
|
||||
**ARM64服务器** (Oracle Cloud, AWS Graviton等):
|
||||
```bash
|
||||
# Docker会自动选择ARM64镜像,无需特殊配置
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
--restart always \
|
||||
-v $PWD/xianyu-auto-reply/:/app/data/ \
|
||||
--name xianyu-auto-reply \
|
||||
registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest
|
||||
```
|
||||
|
||||
### 方式二:从源码构建部署
|
||||
@ -337,7 +377,11 @@ python Start.py
|
||||
- ✅ **linux/amd64** - Intel/AMD处理器(传统服务器、PC、虚拟机)
|
||||
- ✅ **linux/arm64** - ARM64处理器(ARM服务器、树莓派4+、Apple M系列)
|
||||
|
||||
**自动构建**: GitHub Actions自动构建并推送多架构镜像,Docker会自动选择匹配的架构
|
||||
**镜像仓库**:
|
||||
- 🇨🇳 **阿里云**: `registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest`
|
||||
- 🌍 **Docker Hub**: `zhinianblog/xianyu-auto-reply:latest`
|
||||
|
||||
**自动构建**: GitHub Actions自动构建并推送多架构镜像到两个镜像仓库,Docker会自动选择匹配的架构
|
||||
|
||||
**适用的ARM云服务器**:
|
||||
- Oracle Cloud - Ampere A1 (永久免费4核24GB)
|
||||
@ -356,6 +400,9 @@ WEB_PORT=8080 # Web服务端口
|
||||
API_HOST=0.0.0.0 # API服务主机
|
||||
TZ=Asia/Shanghai # 时区设置
|
||||
|
||||
# 数据库配置
|
||||
DB_PATH=data/xianyu_data.db # 数据库文件路径(默认在data目录)
|
||||
|
||||
# 管理员配置
|
||||
ADMIN_USERNAME=admin # 管理员用户名
|
||||
ADMIN_PASSWORD=admin123 # 管理员密码(请修改)
|
||||
@ -734,6 +781,74 @@ CPU_LIMIT=2.0 # CPU限制(核心数)
|
||||
- **日志文件**:`logs/` 目录下的按日期分割的日志文件
|
||||
- **日志级别**:支持DEBUG、INFO、WARNING、ERROR级别
|
||||
|
||||
### Docker容器管理
|
||||
|
||||
**查看容器日志**:
|
||||
```bash
|
||||
# 实时查看日志
|
||||
docker logs -f xianyu-auto-reply
|
||||
|
||||
# 查看最近100行
|
||||
docker logs --tail 100 xianyu-auto-reply
|
||||
```
|
||||
|
||||
**更新到最新版本**:
|
||||
|
||||
国内用户(阿里云镜像):
|
||||
```bash
|
||||
# 1. 停止并删除旧容器
|
||||
docker stop xianyu-auto-reply
|
||||
docker rm xianyu-auto-reply
|
||||
|
||||
# 2. 拉取最新镜像
|
||||
docker pull registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest
|
||||
|
||||
# 3. 启动新容器
|
||||
docker run -d -p 8080:8080 --restart always \
|
||||
-v $PWD/xianyu-auto-reply/:/app/data/ \
|
||||
--name xianyu-auto-reply \
|
||||
registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest
|
||||
```
|
||||
|
||||
国际用户(Docker Hub):
|
||||
```bash
|
||||
# 1. 停止并删除旧容器
|
||||
docker stop xianyu-auto-reply
|
||||
docker rm xianyu-auto-reply
|
||||
|
||||
# 2. 拉取最新镜像
|
||||
docker pull zhinianblog/xianyu-auto-reply:latest
|
||||
|
||||
# 3. 启动新容器
|
||||
docker run -d -p 8080:8080 --restart always \
|
||||
-v $PWD/xianyu-auto-reply/:/app/data/ \
|
||||
--name xianyu-auto-reply \
|
||||
zhinianblog/xianyu-auto-reply:latest
|
||||
```
|
||||
|
||||
**验证多架构镜像**:
|
||||
```bash
|
||||
# 查看镜像支持的架构
|
||||
docker manifest inspect registry.cn-shanghai.aliyuncs.com/zhinian-software/xianyu-auto-reply:latest | grep architecture
|
||||
|
||||
# 或Docker Hub镜像
|
||||
docker manifest inspect zhinianblog/xianyu-auto-reply:latest | grep architecture
|
||||
|
||||
# 应该显示: "architecture": "amd64" 和 "architecture": "arm64"
|
||||
```
|
||||
|
||||
|
||||
**容器重启**:
|
||||
```bash
|
||||
# 重启容器
|
||||
docker restart xianyu-auto-reply
|
||||
|
||||
# 停止容器
|
||||
docker stop xianyu-auto-reply
|
||||
|
||||
# 启动容器
|
||||
docker start xianyu-auto-reply
|
||||
```
|
||||
|
||||
## 🔒 安全特性
|
||||
|
||||
|
||||
91
Start.py
91
Start.py
@ -7,11 +7,98 @@
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
|
||||
# ==================== 在导入任何模块之前先迁移数据库 ====================
|
||||
def _migrate_database_files_early():
|
||||
"""在启动前检查并迁移数据库文件到data目录(使用print,因为logger还未初始化)"""
|
||||
print("检查数据库文件位置...")
|
||||
|
||||
# 确保data目录存在
|
||||
data_dir = Path("data")
|
||||
if not data_dir.exists():
|
||||
data_dir.mkdir(parents=True, exist_ok=True)
|
||||
print("✓ 创建 data 目录")
|
||||
|
||||
# 定义需要迁移的文件
|
||||
files_to_migrate = [
|
||||
("xianyu_data.db", "data/xianyu_data.db", "主数据库"),
|
||||
("user_stats.db", "data/user_stats.db", "统计数据库"),
|
||||
]
|
||||
|
||||
migrated_files = []
|
||||
|
||||
# 迁移主数据库和统计数据库
|
||||
for old_path, new_path, description in files_to_migrate:
|
||||
old_file = Path(old_path)
|
||||
new_file = Path(new_path)
|
||||
|
||||
if old_file.exists():
|
||||
if not new_file.exists():
|
||||
# 新位置不存在,移动文件
|
||||
try:
|
||||
shutil.move(str(old_file), str(new_file))
|
||||
print(f"✓ 迁移{description}: {old_path} -> {new_path}")
|
||||
migrated_files.append(description)
|
||||
except Exception as e:
|
||||
print(f"⚠ 无法迁移{description}: {e}")
|
||||
print(f" 尝试复制文件...")
|
||||
try:
|
||||
shutil.copy2(str(old_file), str(new_file))
|
||||
print(f"✓ 已复制{description}到新位置")
|
||||
print(f" 请在确认数据正常后手动删除: {old_path}")
|
||||
migrated_files.append(f"{description}(已复制)")
|
||||
except Exception as e2:
|
||||
print(f"✗ 复制{description}失败: {e2}")
|
||||
else:
|
||||
# 新位置已存在,检查旧文件大小
|
||||
try:
|
||||
if old_file.stat().st_size > 0:
|
||||
print(f"⚠ 发现旧{description}文件: {old_path}")
|
||||
print(f" 新数据库位于: {new_path}")
|
||||
print(f" 建议备份后删除旧文件")
|
||||
except:
|
||||
pass
|
||||
|
||||
# 迁移备份文件
|
||||
backup_files = list(Path(".").glob("xianyu_data_backup_*.db"))
|
||||
if backup_files:
|
||||
print(f"发现 {len(backup_files)} 个备份文件")
|
||||
backup_migrated = 0
|
||||
for backup_file in backup_files:
|
||||
new_backup_path = data_dir / backup_file.name
|
||||
if not new_backup_path.exists():
|
||||
try:
|
||||
shutil.move(str(backup_file), str(new_backup_path))
|
||||
print(f"✓ 迁移备份文件: {backup_file.name}")
|
||||
backup_migrated += 1
|
||||
except Exception as e:
|
||||
print(f"⚠ 无法迁移备份文件 {backup_file.name}: {e}")
|
||||
|
||||
if backup_migrated > 0:
|
||||
migrated_files.append(f"{backup_migrated}个备份文件")
|
||||
|
||||
# 输出迁移总结
|
||||
if migrated_files:
|
||||
print(f"✓ 数据库迁移完成,已迁移: {', '.join(migrated_files)}")
|
||||
else:
|
||||
print("✓ 数据库文件检查完成")
|
||||
|
||||
return True
|
||||
|
||||
# 在导入 db_manager 之前先执行数据库迁移
|
||||
try:
|
||||
_migrate_database_files_early()
|
||||
except Exception as e:
|
||||
print(f"⚠ 数据库迁移检查失败: {e}")
|
||||
# 继续启动,因为可能是首次运行
|
||||
|
||||
# ==================== 现在可以安全地导入其他模块 ====================
|
||||
import asyncio
|
||||
import threading
|
||||
import uvicorn
|
||||
from urllib.parse import urlparse
|
||||
from pathlib import Path
|
||||
from loguru import logger
|
||||
|
||||
# 修复Linux环境下的asyncio子进程问题
|
||||
@ -56,6 +143,8 @@ def _start_api_server():
|
||||
uvicorn.run("reply_server:app", host=host, port=port, log_level="info")
|
||||
|
||||
|
||||
|
||||
|
||||
def load_keywords_file(path: str):
|
||||
"""从文件读取关键字 -> [(keyword, reply)]"""
|
||||
kw_list = []
|
||||
|
||||
@ -20,7 +20,7 @@ class DBManager:
|
||||
"""初始化数据库连接和表结构"""
|
||||
# 支持环境变量配置数据库路径
|
||||
if db_path is None:
|
||||
db_path = os.getenv('DB_PATH', 'xianyu_data.db')
|
||||
db_path = os.getenv('DB_PATH', 'data/xianyu_data.db')
|
||||
|
||||
# 确保数据目录存在并有正确权限
|
||||
db_dir = os.path.dirname(db_path)
|
||||
|
||||
@ -48,6 +48,34 @@ python -c "import fastapi, uvicorn, loguru, websockets" 2>/dev/null || {
|
||||
}
|
||||
echo "✓ Python 依赖检查完成"
|
||||
|
||||
# 迁移数据库文件到data目录(如果需要)
|
||||
echo "检查数据库文件位置..."
|
||||
if [ -f "/app/xianyu_data.db" ] && [ ! -f "/app/data/xianyu_data.db" ]; then
|
||||
echo "发现旧数据库文件,迁移到data目录..."
|
||||
mv /app/xianyu_data.db /app/data/xianyu_data.db
|
||||
echo "✓ 主数据库已迁移"
|
||||
elif [ -f "/app/xianyu_data.db" ] && [ -f "/app/data/xianyu_data.db" ]; then
|
||||
echo "⚠ 检测到新旧数据库都存在,使用data目录中的数据库"
|
||||
echo " 旧文件: /app/xianyu_data.db"
|
||||
echo " 新文件: /app/data/xianyu_data.db"
|
||||
fi
|
||||
|
||||
if [ -f "/app/user_stats.db" ] && [ ! -f "/app/data/user_stats.db" ]; then
|
||||
echo "迁移统计数据库到data目录..."
|
||||
mv /app/user_stats.db /app/data/user_stats.db
|
||||
echo "✓ 统计数据库已迁移"
|
||||
fi
|
||||
|
||||
# 迁移备份文件
|
||||
backup_count=$(ls /app/xianyu_data_backup_*.db 2>/dev/null | wc -l)
|
||||
if [ "$backup_count" -gt 0 ]; then
|
||||
echo "发现 $backup_count 个备份文件,迁移到data目录..."
|
||||
mv /app/xianyu_data_backup_*.db /app/data/ 2>/dev/null || true
|
||||
echo "✓ 备份文件已迁移"
|
||||
fi
|
||||
|
||||
echo "✓ 数据库文件位置检查完成"
|
||||
|
||||
# 显示启动信息
|
||||
echo "========================================"
|
||||
echo " 系统启动参数:"
|
||||
|
||||
@ -4543,8 +4543,8 @@ def list_backup_files(admin_user: Dict[str, Any] = Depends(require_admin)):
|
||||
try:
|
||||
log_with_user('info', "查询备份文件列表", admin_user)
|
||||
|
||||
# 查找备份文件
|
||||
backup_files = glob.glob("xianyu_data_backup_*.db")
|
||||
# 查找备份文件(在data目录中)
|
||||
backup_files = glob.glob("data/xianyu_data_backup_*.db")
|
||||
|
||||
backup_list = []
|
||||
for file_path in backup_files:
|
||||
|
||||
@ -16,7 +16,7 @@ from pathlib import Path
|
||||
app = FastAPI(title="闲鱼自动回复系统用户统计", version="1.0.0")
|
||||
|
||||
# 数据库文件路径
|
||||
DB_PATH = Path(__file__).parent / "user_stats.db"
|
||||
DB_PATH = Path(__file__).parent / "data" / "user_stats.db"
|
||||
|
||||
|
||||
class UserStats(BaseModel):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user