| FROM walkingd/tgto123:latest |
|
|
| |
| RUN apt-get update && apt-get install -y socat netcat-openbsd && \ |
| pip3 install --no-cache-dir huggingface_hub --break-system-packages && \ |
| rm -rf /var/lib/apt/lists/* |
|
|
| |
| RUN cat > /usr/local/bin/backup.sh << 'EOF' |
| |
| set -e |
|
|
| if [ -z "$HF_DATASET" ] || [ -z "$HF_TOKEN" ]; then |
| echo "❌ 缺少 HF_DATASET 或 HF_TOKEN 环境变量,跳过备份" |
| exit 0 |
| fi |
|
|
| echo "$(date): 📦 开始备份 TgtoDrive 数据..." |
|
|
| mkdir -p /tmp/tgtodrive_backup |
|
|
| |
| for path in /app/db /app/user.env /app/data; do |
| if [ -e "$path" ]; then |
| cp -r "$path" /tmp/tgtodrive_backup/ 2>/dev/null || true |
| echo "✅ 已复制 $path" |
| else |
| echo "⚠️ 未找到 $path" |
| fi |
| done |
|
|
| cd /tmp |
| tar -czf tgtodrive_backup.tar.gz tgtodrive_backup 2>/dev/null || true |
| BACKUP_FILE="/tmp/tgtodrive_backup.tar.gz" |
|
|
| if [ ! -f "$BACKUP_FILE" ]; then |
| echo "❌ 没有数据可备份" |
| exit 0 |
| fi |
|
|
| TIMESTAMP=$(date +%Y%m%d_%H%M%S) |
| REMOTE_PATH="tgtodrive_backup_${TIMESTAMP}.tar.gz" |
|
|
| python3 <<PYEOF |
| from huggingface_hub import HfApi |
| import os |
|
|
| api = HfApi() |
| repo_id = os.environ.get("HF_DATASET") |
| token = os.environ.get("HF_TOKEN") |
| backup_file = "$BACKUP_FILE" |
| remote_path = "$REMOTE_PATH" |
|
|
| try: |
| api.upload_file( |
| path_or_fileobj=backup_file, |
| path_in_repo=remote_path, |
| repo_id=repo_id, |
| repo_type="dataset", |
| token=token |
| ) |
| print(f"✅ 备份上传成功: {remote_path}") |
| except Exception as e: |
| print(f"❌ 备份上传失败: {e}") |
| PYEOF |
|
|
| rm -rf /tmp/tgtodrive_backup /tmp/tgtodrive_backup.tar.gz |
| echo "$(date): 🎉 备份流程完成" |
| EOF |
|
|
| RUN chmod +x /usr/local/bin/backup.sh |
|
|
| |
| RUN cat > /usr/local/bin/start.sh << 'EOF' |
| |
| set -e |
|
|
| |
| if [ -n "$HF_DATASET" ] && [ -n "$HF_TOKEN" ]; then |
| echo "🔄 检查是否存在可恢复的备份..." |
| python3 <<PYEOF |
| from huggingface_hub import HfApi, hf_hub_download |
| import os, tarfile, shutil |
|
|
| repo_id = os.environ.get("HF_DATASET") |
| token = os.environ.get("HF_TOKEN") |
| api = HfApi() |
|
|
| try: |
| files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token) |
| backup_files = [f for f in files if f.startswith("tgtodrive_backup_") and f.endswith(".tar.gz")] |
| if not backup_files: |
| print("📭 未找到历史备份文件") |
| else: |
| backup_files.sort(reverse=True) |
| latest = backup_files[0] |
| print(f"📥 发现最新备份: {latest},正在下载...") |
| path = hf_hub_download( |
| repo_id=repo_id, |
| filename=latest, |
| repo_type="dataset", |
| token=token |
| ) |
| with tarfile.open(path, "r:gz") as tar: |
| tar.extractall(path="/tmp/restore_data") |
| if os.path.exists("/tmp/restore_data/tgtodrive_backup"): |
| for item in os.listdir("/tmp/restore_data/tgtodrive_backup"): |
| src = os.path.join("/tmp/restore_data/tgtodrive_backup", item) |
| dst = os.path.join("/app", item) |
| if os.path.exists(dst): |
| shutil.rmtree(dst) if os.path.isdir(dst) else os.remove(dst) |
| shutil.move(src, dst) |
| print("✅ 数据恢复成功") |
| else: |
| print("⚠️ 备份文件中未找到数据,跳过恢复") |
| shutil.rmtree("/tmp/restore_data", ignore_errors=True) |
| except Exception as e: |
| print(f"⚠️ 恢复过程出现异常: {e}") |
| PYEOF |
| fi |
|
|
| |
| echo "🚀 启动 TgtoDrive 主服务..." |
| if [ -f "/app/tgto123" ]; then |
| /app/tgto123 & |
| elif [ -f "/app/tgto123.pyc" ]; then |
| python -O /app/tgto123.pyc & |
| else |
| echo "❌ 找不到可执行文件" |
| exit 1 |
| fi |
| MAIN_PID=$! |
|
|
| |
| echo "⏳ 等待主服务端口 12366 就绪..." |
| while ! nc -z 127.0.0.1 12366 2>/dev/null; do |
| sleep 1 |
| done |
| echo "✅ 主服务端口已就绪" |
|
|
| |
| echo "🔌 启动端口转发 7860 -> 12366" |
| socat TCP-LISTEN:7860,fork TCP:127.0.0.1:12366 & |
| SOCAT_PID=$! |
|
|
| |
| echo "⏰ 启动自动备份(每30分钟)..." |
| ( |
| while true; do |
| sleep 1800 |
| /usr/local/bin/backup.sh |
| done |
| ) & |
| BACKUP_PID=$! |
|
|
| trap 'echo "🛑 容器停止,执行最后一次备份..."; /usr/local/bin/backup.sh; kill $MAIN_PID $SOCAT_PID $BACKUP_PID 2>/dev/null' EXIT |
|
|
| wait $MAIN_PID |
| EOF |
|
|
| RUN chmod +x /usr/local/bin/start.sh |
|
|
| EXPOSE 7860 |
| CMD ["/usr/local/bin/start.sh"] |