File size: 7,110 Bytes
3f49de3 687d8aa 3f49de3 4bc980d 3f49de3 687d8aa 6749611 416d80d 687d8aa f444687 416d80d 687d8aa 416d80d 687d8aa 416d80d 687d8aa 1b4a82a b204b33 687d8aa b204b33 f33cde5 b204b33 d4e00ce b204b33 f33cde5 b204b33 1b4a82a b204b33 e6a5980 b204b33 e6a5980 b204b33 f33cde5 b204b33 1b4a82a f33cde5 1b4a82a 6749611 1b4a82a e6a5980 b204b33 1b4a82a b204b33 e6a5980 b204b33 1b4a82a 5cb2a86 e52cf6c f444687 e52cf6c d7433d1 f444687 e52cf6c d4e00ce e52cf6c f444687 e52cf6c 6749611 e52cf6c 1b4a82a b204b33 e52cf6c b204b33 e6a5980 f33cde5 b204b33 1b4a82a e6a5980 f33cde5 1b4a82a f33cde5 1b4a82a e52cf6c 1b4a82a f33cde5 e6a5980 f33cde5 e6a5980 f444687 e52cf6c b204b33 1b4a82a e52cf6c f33cde5 e6a5980 b204b33 e52cf6c b204b33 687d8aa 3f49de3 | 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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | FROM node:22-slim
# 1. 基础依赖补全
RUN apt-get update && apt-get install -y --no-install-recommends \
git openssh-client build-essential python3 python3-pip \
g++ make ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# 2. 安装 HF 数据交互工具
RUN pip3 install --no-cache-dir huggingface_hub --break-system-packages
# 3. 构建环境优化
RUN update-ca-certificates && \
git config --global http.sslVerify false && \
git config --global url."https://github.com/".insteadOf ssh://git@github.com/
# 4. OpenClaw 核心安装
RUN npm install -g openclaw@latest --unsafe-perm
# 5. 环境变量预设
ENV PORT=7860 \
OPENCLAW_GATEWAY_MODE=local \
HOME=/root
# 6. Python 同步引擎(已新增定时任务完整备份)
RUN cat > /usr/local/bin/sync.py << 'EOF'
import os, sys, tarfile
from huggingface_hub import HfApi, hf_hub_download
from datetime import datetime, timedelta
api = HfApi()
repo_id = os.getenv("HF_DATASET")
token = os.getenv("HF_TOKEN")
def restore():
try:
print("🔍 [Restore] Searching for latest backup...")
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)
now = datetime.now()
for i in range(7):
day = (now - timedelta(days=i)).strftime("%Y-%m-%d")
name = f"backup_{day}.tar.gz"
if name in files:
print(f"📦 [Restore] Found: {name}")
path = hf_hub_download(repo_id=repo_id, filename=name, repo_type="dataset", token=token)
with tarfile.open(path, "r:gz") as tar:
tar.extractall(path="/root/.openclaw/")
print(f"✅ [Restore] Success: Restored sessions + skills + scheduled tasks + agents from {name}")
return True
print("⚠️ [Restore] No recent backup found.")
except Exception as e:
print(f"❌ [Restore] Error: {e}")
def backup():
try:
day = datetime.now().strftime("%Y-%m-%d")
name = f"backup_{day}.tar.gz"
print(f"📦 [Backup] Starting → {name}")
with tarfile.open(name, "w:gz") as tar:
# 会话
if os.path.exists("/root/.openclaw/agents"):
tar.add("/root/.openclaw/agents", arcname="agents")
session_count = len(os.listdir("/root/.openclaw/agents/main/sessions")) if os.path.exists("/root/.openclaw/agents/main/sessions") else 0
print(f" → Backed up agents/sessions ({session_count} sessions)")
# 技能
if os.path.exists("/root/.openclaw/skills"):
tar.add("/root/.openclaw/skills", arcname="skills")
if os.path.exists("/root/.openclaw/workspace"):
tar.add("/root/.openclaw/workspace", arcname="workspace")
# 定时任务(新增重点)
if os.path.exists("/root/.openclaw/cron"):
tar.add("/root/.openclaw/cron", arcname="cron")
print(" → Backed up cron/ (scheduled tasks)")
if os.path.exists("/root/.openclaw/agents/main/cron"):
tar.add("/root/.openclaw/agents/main/cron", arcname="agents/main/cron")
print(" → Backed up agents/main/cron")
if os.path.exists("/root/.openclaw/workspace/cron"):
tar.add("/root/.openclaw/workspace/cron", arcname="workspace/cron")
print(" → Backed up workspace/cron")
# 其他必要目录
if os.path.exists("/root/.openclaw/openclaw.json"):
tar.add("/root/.openclaw/openclaw.json", arcname="openclaw.json")
if os.path.exists("/root/.openclaw/.clawhub"):
tar.add("/root/.openclaw/.clawhub", arcname=".clawhub")
api.upload_file(path_or_fileobj=name, path_in_repo=name, repo_id=repo_id, repo_type="dataset", token=token)
print(f"✅ [Backup] Success: {name} uploaded (includes scheduled tasks)")
except Exception as e:
print(f"❌ [Backup] Error: {e}")
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "backup":
backup()
else:
restore()
EOF
# 7. openclaw.json 模板(你的第三方 API 配置)
RUN mkdir -p /root/.openclaw && \
cat > /root/.openclaw/openclaw.json.template << 'EOT'
{
"models": {
"providers": {
"thirdparty": {
"baseUrl": "PLACEHOLDER_BASE_URL",
"apiKey": "PLACEHOLDER_API_KEY",
"api": "openai-completions",
"models": [
{
"id": "gemini-3.1-pro-high",
"name": "Gemini 3.1 Pro (High)",
"contextWindow": 131072
}
]
}
}
},
"agents": {
"defaults": {
"timeoutSeconds": 300, // 整体任务超时,建议 300(5分钟)或更高
"model": {
"primary": "thirdparty/PLACEHOLDER_MODEL_ID"
}
}
},
"gateway": {
"mode": "local",
"bind": "lan",
"port": 7860,
"trustedProxies": ["0.0.0.0/0", "10.0.0.0/8", "10.16.0.0/12", "172.16.0.0/12", "192.168.0.0/16"],
"auth": {
"mode": "token",
"token": "PLACEHOLDER_GATEWAY_PASSWORD"
},
"controlUi": {
"enabled": true,
"allowInsecureAuth": true,
"dangerouslyAllowHostHeaderOriginFallback": true,
"dangerouslyDisableDeviceAuth": true
}
}
}
EOT
# 8. 启动脚本(显示定时任务恢复情况)
RUN cat > /usr/local/bin/start-openclaw << 'EOF'
#!/bin/bash
set -e
mkdir -p /root/.openclaw/sessions
echo "🚀 Starting OpenClaw with full persistence..."
# 恢复所有数据
python3 /usr/local/bin/sync.py restore
# 显示恢复后的会话和定时任务
echo "=== Restored Sessions ==="
if [ -d "/root/.openclaw/agents/main/sessions" ]; then
count=$(ls -1 "/root/.openclaw/agents/main/sessions" 2>/dev/null | wc -l)
echo "agents/main/sessions: ${count} sessions"
else
echo "No agents/main/sessions yet"
fi
echo "=== Restored Scheduled Tasks (cron) ==="
ls -la /root/.openclaw/cron 2>/dev/null || echo "No global cron"
ls -la /root/.openclaw/agents/main/cron 2>/dev/null || echo "No agents/main/cron"
ls -la /root/.openclaw/workspace/cron 2>/dev/null || echo "No workspace/cron"
echo "=================================="
# 立即备份一次
echo "📤 Immediate backup after restore..."
python3 /usr/local/bin/sync.py backup
# 生成配置
CLEAN_BASE=$(echo "$OPENAI_API_BASE" | sed 's|/chat/completions||g' | sed 's|/v1/|/v1|g' | sed 's|/v1$|/v1|g')
sed -e "s|PLACEHOLDER_BASE_URL|$CLEAN_BASE|g" \
-e "s|PLACEHOLDER_API_KEY|$OPENAI_API_KEY|g" \
-e "s|PLACEHOLDER_MODEL_ID|$MODEL|g" \
-e "s|PLACEHOLDER_GATEWAY_PASSWORD|$OPENCLAW_GATEWAY_PASSWORD|g" \
/root/.openclaw/openclaw.json.template > /root/.openclaw/openclaw.json
echo "✅ OpenClaw fully started (sessions + skills + scheduled tasks restored)"
# 每20分钟自动备份
(while true; do sleep 1200; python3 /usr/local/bin/sync.py backup; done) &
openclaw doctor --fix
exec openclaw gateway run --port $PORT
EOF
RUN chmod +x /usr/local/bin/start-openclaw
EXPOSE 7860
CMD ["/usr/local/bin/start-openclaw"] |