| FROM gitea/gitea:1.24.6 |
|
|
| |
| USER root |
|
|
| |
| RUN apk update && \ |
| apk add python3 py3-pip && \ |
| pip3 install --break-system-packages --upgrade pip |
|
|
| |
| RUN pip3 install --break-system-packages watchdog huggingface_hub |
|
|
| |
| RUN mkdir -p /data/gitea /data/git /data/ssh && \ |
| chown -R git:git /data && \ |
| chmod -R 750 /data |
|
|
| |
| WORKDIR /data |
|
|
| |
| EXPOSE 7860 |
|
|
| |
| ENV GITEA__database__DB_TYPE=sqlite3 \ |
| GITEA__database__PATH=/data/gitea/gitea.db \ |
| GITEA__server__ROOT_URL=https://deep-sea-02gitea.hf.space/ \ |
| GITEA__server__HTTP_ADDR=0.0.0.0 \ |
| GITEA__server__HTTP_PORT=7860 \ |
| GITEA__server__DISABLE_SSH=true \ |
| USER=git |
|
|
| |
| USER git |
|
|
| COPY --chown=git:git <<'EOF' /uploadhf.py |
| import os |
| import time |
| import logging |
| import threading |
| import subprocess |
| from pathlib import Path |
| from watchdog.observers import Observer |
| from watchdog.events import FileSystemEventHandler |
| from huggingface_hub import HfApi |
|
|
| |
| logging.basicConfig( |
| level=logging.INFO, |
| format='%(asctime)s - %(levelname)s - %(message)s' |
| ) |
| logger = logging.getLogger(__name__) |
|
|
| class DataDirectoryHandler(FileSystemEventHandler): |
| """处理 /data 目录文件变化的监控器""" |
| |
| def __init__(self, repo_id, hf_token, data_directory="/data"): |
| self.repo_id = repo_id |
| self.hf_token = hf_token |
| self.data_directory = data_directory |
| self.api = HfApi(token=hf_token) |
| self.last_commit_time = 0 |
| self.commit_delay = 30 |
| logger.info(f"初始化监控器,监控目录: {data_directory},目标仓库: {repo_id}") |
| |
| def on_modified(self, event): |
| """文件被修改时触发""" |
| if not event.is_directory: |
| logger.info(f"检测到文件修改: {event.src_path}") |
| self.schedule_commit("文件修改") |
| |
| def on_created(self, event): |
| """文件被创建时触发""" |
| if not event.is_directory: |
| logger.info(f"检测到新文件: {event.src_path}") |
| self.schedule_commit("文件创建") |
| |
| def on_deleted(self, event): |
| """文件被删除时触发""" |
| if not event.is_directory: |
| logger.info(f"检测到文件删除: {event.src_path}") |
| self.schedule_commit("文件删除") |
| |
| def on_moved(self, event): |
| """文件被移动或重命名时触发""" |
| logger.info(f"检测到文件移动: {event.src_path} -> {event.dest_path}") |
| self.schedule_commit("文件移动") |
| |
| def schedule_commit(self, change_type): |
| """安排提交任务,带有防抖机制""" |
| current_time = time.time() |
| if current_time - self.last_commit_time > self.commit_delay: |
| self.last_commit_time = current_time |
| |
| thread = threading.Thread(target=self.commit_changes, args=(change_type,)) |
| thread.daemon = True |
| thread.start() |
| |
| def commit_changes(self, change_type): |
| """提交变更到 Hugging Face Hub""" |
| try: |
| commit_message = f"自动提交: {change_type} - {time.strftime('%Y-%m-%d %H:%M:%S')}" |
| |
| |
| self.api.upload_folder( |
| folder_path=self.data_directory, |
| repo_id=self.repo_id, |
| repo_type="dataset", |
| commit_message=commit_message, |
| ignore_patterns=["*.tmp", "*.log", "*.temp", ".git/*"] |
| ) |
| |
| logger.info(f"✅ 成功提交变更到 Hugging Face Hub: {commit_message}") |
| |
| except Exception as e: |
| logger.error(f"❌ 提交失败: {e}") |
|
|
| def start_directory_monitoring(data_directory="/data", repo_id=None, hf_token=None): |
| """启动目录监控服务""" |
| |
| if not hf_token: |
| hf_token = os.getenv('HF_TOKEN') |
| if not hf_token: |
| raise ValueError("HF_TOKEN 环境变量未设置") |
| |
| if not repo_id: |
| raise ValueError("必须提供 repo_id 参数") |
| |
| |
| if not os.path.exists(data_directory): |
| logger.warning(f"监控目录 {data_directory} 不存在,正在创建...") |
| os.makedirs(data_directory, exist_ok=True) |
| |
| |
| event_handler = DataDirectoryHandler( |
| repo_id=repo_id, |
| hf_token=hf_token, |
| data_directory=data_directory |
| ) |
| |
| observer = Observer() |
| observer.schedule(event_handler, data_directory, recursive=True) |
| |
| |
| observer.start() |
| logger.info(f"🎯 目录监控服务已启动: {data_directory}") |
| |
| return observer |
|
|
| def start_gitea_server(port=7860): |
| """启动 Gitea 服务器[1,3](@ref)""" |
| def run_gitea(): |
| try: |
| |
| gitea_process = subprocess.Popen( |
| ['gitea', 'web', '--port', str(port)], |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE, |
| universal_newlines=True |
| ) |
| |
| logger.info(f"🚀 Gitea 服务器已启动,端口: {port}") |
| logger.info(f"📊 访问地址: http://localhost:{port}") |
| |
| |
| while True: |
| output = gitea_process.stdout.readline() |
| if output == '' and gitea_process.poll() is not None: |
| break |
| if output: |
| logger.info(f"Gitea: {output.strip()}") |
| |
| |
| return_code = gitea_process.poll() |
| if return_code != 0: |
| error_output = gitea_process.stderr.read() |
| logger.error(f"❌ Gitea 服务器异常退出,返回码: {return_code}") |
| logger.error(f"错误信息: {error_output}") |
| else: |
| logger.info("✅ Gitea 服务器正常退出") |
| |
| except FileNotFoundError: |
| logger.error("❌ 未找到 gitea 命令,请确保 Gitea 已正确安装") |
| except Exception as e: |
| logger.error(f"❌ 启动 Gitea 服务器时发生错误: {e}") |
| |
| |
| gitea_thread = threading.Thread(target=run_gitea) |
| gitea_thread.daemon = True |
| gitea_thread.start() |
| |
| return gitea_thread |
|
|
| def main(): |
| """主函数 - 同时启动目录监控和 Gitea 服务器""" |
| |
| CONFIG = { |
| "data_directory": "/data", |
| "repo_id": "02engine/02gitea", |
| "hf_token": os.getenv('HF_TOKEN'), |
| "gitea_port": 7860 |
| } |
| |
| |
| if not CONFIG["hf_token"]: |
| logger.error("❌ 请设置 HF_TOKEN 环境变量") |
| return |
| |
| logger.info("🚀 启动集成服务...") |
| |
| try: |
| |
| gitea_thread = start_gitea_server(CONFIG["gitea_port"]) |
| |
| |
| observer = start_directory_monitoring( |
| data_directory=CONFIG["data_directory"], |
| repo_id=CONFIG["repo_id"], |
| hf_token=CONFIG["hf_token"] |
| ) |
| |
| logger.info("✅ 所有服务已启动完成!") |
| logger.info("调试: HF_TOKEN = %s", CONFIG["hf_token"]) |
| logger.info("📁 目录监控: /data → Hugging Face Hub") |
| logger.info("🌐 Gitea 服务: http://localhost:7860") |
| logger.info("🛑 按 Ctrl+C 停止所有服务") |
| |
| |
| try: |
| while True: |
| time.sleep(1) |
| except KeyboardInterrupt: |
| logger.info("正在停止所有服务...") |
| |
| except Exception as e: |
| logger.error(f"❌ 启动服务时发生错误: {e}") |
| finally: |
| |
| if 'observer' in locals(): |
| observer.stop() |
| observer.join() |
| logger.info("所有服务已停止") |
|
|
| if __name__ == "__main__": |
| main() |
| EOF |
|
|
| |
| RUN cat /uploadhf.py |
| CMD ["python3", "/uploadhf.py"] |