| |
| FROM node:22-slim |
|
|
| RUN apt-get update && apt-get install -y |
| && rm -rf /var/lib/apt/lists/* |
|
|
| RUN apt-get update && apt-get install -y |
| git openssh-client build-essential python3 python3-pip g++ make ca-certificates \ |
| && rm -rf /var/lib/apt/lists/* |
|
|
| RUN pip3 install |
|
|
| RUN update-ca-certificates |
|
|
| RUN npm install -g openclaw@latest |
|
|
| RUN mkdir -p /home/node/.openclaw && chown -R node:node /home/node/.openclaw |
|
|
| ENV PORT=7860 \ |
| OPENCLAW_GATEWAY_MODE=local \ |
| HOME=/home/node |
|
|
| |
| RUN echo 'import os, sys, tarfile\n\ |
| from huggingface_hub import HfApi, hf_hub_download\n\ |
| from datetime import datetime, timedelta\n\ |
| \n\ |
| api = HfApi()\n\ |
| repo_id = os.getenv("HF_DATASET")\n\ |
| token = os.getenv("HF_TOKEN")\n\ |
| DATA_DIR = os.path.expanduser("~/.openclaw")\n\ |
| \n\ |
| def restore():\n\ |
| try:\n\ |
| print(f"--- [SYNC] 启动恢复流程, 目标仓库: {repo_id} ---")\n\ |
| if not repo_id or not token:\n\ |
| print("--- [SYNC] 跳过恢复: 未配置 HF_DATASET 或 HF_TOKEN ---")\n\ |
| return False\n\ |
| files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)\n\ |
| now = datetime.now()\n\ |
| for i in range(5):\n\ |
| day = (now - timedelta(days=i)).strftime("%Y-%m-%d")\n\ |
| name = f"backup_{day}.tar.gz"\n\ |
| if name in files:\n\ |
| print(f"--- [SYNC] 发现备份文件: {name}, 正在下载... ---")\n\ |
| path = hf_hub_download(repo_id=repo_id, filename=name, repo_type="dataset", token=token)\n\ |
| with tarfile.open(path, "r:gz") as tar:\n\ |
| tar.extractall(path=DATA_DIR)\n\ |
| print(f"--- [SYNC] 恢复成功! 数据已覆盖至 {DATA_DIR} ---")\n\ |
| return True\n\ |
| print("--- [SYNC] 未找到最近 5 天的备份包 ---")\n\ |
| except Exception as e:\n\ |
| print(f"--- [SYNC] 恢复异常: {e} ---")\n\ |
| \n\ |
| def backup():\n\ |
| try:\n\ |
| targets = ["sessions", "workspace", "agents", "memory"]\n\ |
| existing = [t for t in targets if os.path.exists(os.path.join(DATA_DIR, t))]\n\ |
| if not existing:\n\ |
| print("--- [SYNC] 没有需要备份的数据,跳过备份 ---")\n\ |
| return\n\ |
| day = datetime.now().strftime("%Y-%m-%d")\n\ |
| name = f"backup_{day}.tar.gz"\n\ |
| print(f"--- [SYNC] 正在执行全量备份: {name} ---")\n\ |
| with tarfile.open(name, "w:gz") as tar:\n\ |
| for target in existing:\n\ |
| tar.add(os.path.join(DATA_DIR, target), arcname=target)\n\ |
| api.upload_file(path_or_fileobj=name, path_in_repo=name, repo_id=repo_id, repo_type="dataset", token=token)\n\ |
| print(f"--- [SYNC] 备份上传成功! ---")\n\ |
| os.remove(name)\n\ |
| except Exception as e:\n\ |
| print(f"--- [SYNC] 备份失败: {e} ---")\n\ |
| \n\ |
| if __name__ == "__main__":\n\ |
| if len(sys.argv) > 1 and sys.argv[1] == "backup":\n\ |
| backup()\n\ |
| else:\n\ |
| restore()\n\ |
| ' > /usr/local/bin/sync.py |
|
|
| |
| RUN printf ' |
| : "${OPENAI_API_BASE:?OPENAI_API_BASE not set}"\n\ |
| : "${OPENAI_API_KEY:?OPENAI_API_KEY not set}"\n\ |
| : "${MODEL:?MODEL not set}"\n\ |
| : "${OPENCLAW_GATEWAY_PASSWORD:?OPENCLAW_GATEWAY_PASSWORD not set}"\n\n\ |
| DATA_DIR="$HOME/.openclaw"\n\ |
| mkdir -p "$DATA_DIR"/{sessions,workspace,agents/main/sessions}\n\n\ |
| python3 /usr/local/bin/sync.py restore\n\n\ |
| |
| cat > "$DATA_DIR/openclaw.json" <<JSON\n\ |
| {\n\ |
| "models": {\n\ |
| "providers": {\n\ |
| "openai-compat": {\n\ |
| "baseUrl": "$OPENAI_API_BASE",\n\ |
| "apiKey": "$OPENAI_API_KEY",\n\ |
| "api": "openai-completions",\n\ |
| "models": [{ "id": "$MODEL", "name": "Model", "contextWindow": 128000 }]\n\ |
| }\n\ |
| }\n\ |
| },\n\ |
| "agents": { "defaults": { "model": { "primary": "openai-compat/$MODEL" } } },\n\ |
| "gateway": {\n\ |
| "mode": "local",\n\ |
| "bind": "lan",\n\ |
| "port": $PORT,\n\ |
| "trustedProxies": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],\n\ |
| "auth": { "mode": "token", "token": "$OPENCLAW_GATEWAY_PASSWORD" },\n\ |
| "controlUi": {\n\ |
| "allowInsecureAuth": true,\n\ |
| "dangerouslyDisableDeviceAuth": true,\n\ |
| "allowedOrigins": ["https://ted1990-openclaw.hf.space"]\n\ |
| }\n\ |
| }\n\ |
| }\n\ |
| JSON\n\n\ |
| chmod 700 "$DATA_DIR"\n\ |
| chmod 600 "$DATA_DIR/openclaw.json"\n\n\ |
| echo ""\n\ |
| echo "--- [CONFIG] openclaw.json 已生成 ---"\n\ |
| echo "--- [CONFIG] API Base: $OPENAI_API_BASE ---"\n\ |
| echo "--- [CONFIG] Model: $MODEL ---"\n\ |
| echo ""\n\n\ |
| (while true; do sleep 10800; python3 /usr/local/bin/sync.py backup; done) &\n\n\ |
| (\n\ |
| sleep 8\n\ |
| echo ""\n\ |
| echo "================================================="\n\ |
| echo "✅ OpenClaw 已就绪!请使用以下完整 URL 访问:"\n\ |
| echo "🔗 https://ted1990-openclaw.hf.space/#token=${OPENCLAW_GATEWAY_PASSWORD}"\n\ |
| echo "================================================="\n\ |
| ) &\n\n\ |
| exec openclaw gateway run |
|
|
| USER node |
| EXPOSE 7860 |
| ENTRYPOINT ["/usr/bin/tini", "--"] |
| CMD ["/usr/local/bin/start-openclaw"] |