File size: 7,656 Bytes
35e3473 89fb578 35e3473 89fb578 856c871 89fb578 35e3473 eb76166 3af9e5e 35e3473 856c871 35e3473 360f9c4 35e3473 360f9c4 35e3473 eb76166 35e3473 360f9c4 35e3473 eb76166 3af9e5e fb619df 3af9e5e 35e3473 3d980a7 35e3473 5aa59e4 87f529e 5aa59e4 87f529e fb619df 5aa59e4 87f529e ac84c85 87f529e 5aa59e4 87f529e ac84c85 87f529e 5aa59e4 fb619df 5aa59e4 35e3473 ce3413f 35e3473 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# 核心镜像:Node 22 slim 保证了环境的现代性与轻量化
FROM node:22-slim
# 1. 安装系统依赖
# 包含:git (拉取依赖), openssh-client (解决构建报错), build-essential/g++/make (编译原生模块), python3 (运行同步脚本)
# 新增:curl, chromium (浏览器工具支持), 以及运行 Chromium 所需的库, tzdata (设置时区)
RUN apt-get update && apt-get install -y --no-install-recommends \
git openssh-client build-essential python3 python3-pip \
g++ make ca-certificates curl chromium tzdata \
libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
libxcomposite1 libxdamage1 libxext6 libxfixes3 libxrandr2 \
libgbm1 libasound2 libpangocairo-1.0-0 libpango-1.0-0 \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& rm -rf /var/lib/apt/lists/*
# 2. 安装 Hugging Face 命令行工具
RUN pip3 install --no-cache-dir huggingface_hub --break-system-packages
# 3. 构建环境优化
# 修复 Git 证书问题并将所有 SSH 协议重定向为 HTTPS
RUN update-ca-certificates && \
git config --global http.sslVerify false && \
git config --global url."https://github.com/".insteadOf ssh://git@github.com/
# 4. 全局安装 OpenClaw
ENV HOME=/root
RUN npm install -g openclaw@latest zod --unsafe-perm
# 5. 设置环境变量
ENV PORT=7860 \
OPENCLAW_GATEWAY_MODE=local \
OPENCLAW_BROWSER_PATH=/usr/bin/chromium
# 6. 核心同步引擎 (sync.py)
# 针对 OpenClaw 新版 MEMORY.md 机制进行了全路径覆盖
RUN echo 'import os, sys, tarfile\n\
from huggingface_hub import HfApi, hf_hub_download\n\
from datetime import datetime, timedelta\n\
api = HfApi()\n\
repo_id = os.getenv("HF_DATASET")\n\
token = os.getenv("HF_TOKEN")\n\
\n\
def restore():\n\
try:\n\
print(f"--- [SYNC] 启动恢复流程, 目标仓库: {repo_id} ---")\n\
if repo_id and token:\n\
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)\n\
now = datetime.now()\n\
found = False\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: tar.extractall(path="/root/.openclaw/")\n\
print(f"--- [SYNC] 恢复成功! 数据已覆盖至 /root/.openclaw/ ---")\n\
found = True; break\n\
if not found: print("--- [SYNC] 未找到最近 5 天的备份包 ---")\n\
else: print("--- [SYNC] 跳过恢复: 未配置 HF_DATASET 或 HF_TOKEN ---")\n\
\n\
# 强制清理所有残留的 .lock 文件,防止 session 锁定错误\n\
count = 0\n\
for root, _, fs in os.walk("/root/.openclaw/"):\n\
for f in fs:\n\
if f.endswith(".lock"):\n\
try:\n\
os.remove(os.path.join(root, f))\n\
count += 1\n\
except: pass\n\
if count > 0: print(f"--- [SYNC] 已清理 {count} 个残留的锁定文件 ---")\n\
return True\n\
except Exception as e: print(f"--- [SYNC] 恢复异常: {e} ---")\n\
\n\
def backup():\n\
try:\n\
day = datetime.now().strftime("%Y-%m-%d")\n\
name = f"backup_{day}.tar.gz"\n\
print(f"--- [SYNC] 正在执行全量备份: {name} ---")\n\
def lock_filter(tarinfo):\n\
if tarinfo.name.endswith(".lock"): return None\n\
return tarinfo\n\
with tarfile.open(name, "w:gz") as tar:\n\
for target in ["sessions", "workspace", "agents", "memory", "plugins", "openclaw.json"]:\n\
full_path = f"/root/.openclaw/{target}"\n\
if os.path.exists(full_path):\n\
tar.add(full_path, arcname=target, filter=lock_filter)\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\
except Exception as e: print(f"--- [SYNC] 备份失败: {e} ---")\n\
\n\
if __name__ == "__main__":\n\
if len(sys.argv) > 1 and sys.argv[1] == "backup": backup()\n\
else: restore()' > /usr/local/bin/sync.py
# 7. 容器入口脚本 (start-openclaw)
# 负责恢复数据 -> 生成配置 -> 启动网关 -> 定时备份
RUN echo "#!/bin/bash\n\
set -e\n\
mkdir -p /root/.openclaw/sessions\n\
mkdir -p /root/.openclaw/workspace\n\
mkdir -p /root/.openclaw/plugins\n\
mkdir -p /root/.openclaw/agents/main/sessions\n\
mkdir -p /root/.openclaw/credentials\n\
ln -s /root/.openclaw/workspace /root/.openclaw/memory\n\
chmod 700 /root/.openclaw\n\
\n\
# 启动前执行数据恢复\n\
python3 /usr/local/bin/sync.py restore\n\
\n\
# 设置 CLI 认证 Token\n\
export OPENCLAW_GATEWAY_TOKEN=\"\$OPENCLAW_GATEWAY_PASSWORD\"\n\
\n\
# 清理 API Base 地址\n\
CLEAN_BASE=\$(echo \"\$OPENAI_API_BASE\" | sed \"s|/chat/completions||g\" | sed \"s|/v1/|/v1|g\" | sed \"s|/v1\$|/v1|g\")\n\
\n\
# 生成 openclaw.json 配置文件\n\
cat > /root/.openclaw/openclaw.json <<EOF\n\
{\n\
\"models\": {\n\
\"mode\": \"merge\",\n\
\"providers\": {\n\
\"cliproxy\": {\n\
\"baseUrl\": \"\$OPENAI_API_BASE\",\n\
\"apiKey\": \"\$OPENAI_API_KEY\",\n\
\"api\": \"openai-completions\",\n\
\"models\": [\n\
{\"id\": \"gemini-2.5-pro\", \"name\": \"gemini-2.5-pro\", \"contextWindow\": 200000, \"maxTokens\": 8192},\n\
{\"id\": \"gemini-2.5-flash\", \"name\": \"gemini-2.5-flash\", \"contextWindow\": 200000, \"maxTokens\": 8192},\n\
{\"id\": \"gemini-3-flash-preview\", \"name\": \"gemini-3-flash-preview\", \"contextWindow\": 200000, \"maxTokens\": 8192},\n\
{\"id\": \"gemini-3-pro-preview\", \"name\": \"gemini-3-pro-preview\", \"contextWindow\": 200000, \"maxTokens\": 8192}\n\
]\n\
}\n\
}\n\
},\n\
\"agents\": {\n\
\"defaults\": {\n\
\"model\": {\"primary\": \"cliproxy/gemini-3-flash-preview\", \"fallbacks\": [\"cliproxy/gemini-3-pro-preview\"]},\n\
\"workspace\": \"~/.openclaw/workspace\"\n\
}\n\
},\n\
\"gateway\": {\n\
\"mode\": \"local\", \"bind\": \"lan\", \"port\": \$PORT,\n\
\"trustedProxies\": [\"0.0.0.0/0\", \"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\": { \"allowInsecureAuth\": true }\n\
},\n\
\"channels\": {\n\
\"feishu\": {\n\
\"enabled\": \${FEISHU_ENABLED:-false},\n\
\"appId\": \"\$FEISHU_APP_ID\",\n\
\"appSecret\": \"\$FEISHU_APP_SECRET\",\n\
\"domain\": \"\${FEISHU_DOMAIN:-feishu}\",\n\
\"connectionMode\": \"\${FEISHU_CONNECTION_MODE:-websocket}\",\n\
\"dmPolicy\": \"open\",\n\
\"ignoreEvents\": [\"im.message.message_read_v1\", \"im.chat.access_event.bot_p2p_chat_entered_v1\"]\n\
}\n\
}\n\
}\n\
EOF\n\
\n\
# 启动定时备份进程 (每 3 小时执行一次,增强安全性)\n\
(while true; do sleep 10800; python3 /usr/local/bin/sync.py backup; done) &\n\
\n\
# 启动 OpenClaw 网关\n\
openclaw doctor --fix\n\
exec openclaw gateway run --port \$PORT\n\
" > /usr/local/bin/start-openclaw && chmod +x /usr/local/bin/start-openclaw
EXPOSE 7860
CMD ["/usr/local/bin/start-openclaw"] |