File size: 5,612 Bytes
35e3473 01e197e 35e3473 89fb578 856c871 01e197e 89fb578 35e3473 01e197e 35e3473 01e197e 35e3473 eb76166 35e3473 856c871 35e3473 01e197e 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 | FROM node:22-slim
# Install system dependencies
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/*
# Install Python packages
RUN pip3 install --no-cache-dir huggingface_hub --break-system-packages
# Git and CA config
RUN update-ca-certificates && \
git config --global http.sslVerify false && \
git config --global url."https://github.com/".insteadOf ssh://git@github.com/
ENV HOME=/root
ENV PORT=7860 \
OPENCLAW_GATEWAY_MODE=local \
OPENCLAW_BROWSER_PATH=/usr/bin/chromium
# Install OpenClaw
RUN npm install -g openclaw@latest zod --unsafe-perm
# Generate sync.py using a Heredoc to avoid syntax/escaping issues
RUN cat <<'EOF' > /usr/local/bin/sync.py
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(f"--- [SYNC] Start recovery process, target repository: {repo_id} ---")
if repo_id and token:
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)
now = datetime.now()
found = False
for i in range(5):
day = (now - timedelta(days=i)).strftime("%Y-%m-%d")
name = f"backup_{day}.tar.gz"
if name in files:
print(f"--- [SYNC] Backup file found: {name}, Downloading... ---")
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"--- [SYNC] Recovery successful! ---")
found = True
break
if not found:
print("--- [SYNC] No backup packages found for the last 5 days---")
else:
print("--- [SYNC] Skip recovery: HF_DATASET or HF_TOKEN not configured ---")
# Clean up .lock files
count = 0
for root, dirs, fs in os.walk("/root/.openclaw/"):
for f in fs:
if f.endswith(".lock"):
try:
os.remove(os.path.join(root, f))
count += 1
except: pass
if count > 0:
print(f"--- [SYNC] {count} residual lock files cleaned up---")
return True
except Exception as e:
print(f"--- [SYNC] Recovery Exception: {e} ---")
def backup():
try:
day = datetime.now().strftime("%Y-%m-%d")
name = f"backup_{day}.tar.gz"
print(f"--- [SYNC] Performing a full backup: {name} ---")
def lock_filter(tarinfo):
if tarinfo.name.endswith(".lock"): return None
return tarinfo
with tarfile.open(name, "w:gz") as tar:
for target in ["sessions", "workspace", "agents", "memory", "plugins", "openclaw.json"]:
full_path = f"/root/.openclaw/{target}"
if os.path.exists(full_path):
tar.add(full_path, arcname=target, filter=lock_filter)
if repo_id and token:
api.upload_file(path_or_fileobj=name, path_in_repo=name, repo_id=repo_id, repo_type="dataset", token=token)
print("--- [SYNC] Backup upload successful! ---")
except Exception as e:
print(f"--- [SYNC] Backup failed: {e} ---")
if __name__ == "__main__":
if len(sys.argv) > 1 and sys.argv[1] == "backup":
backup()
else:
restore()
EOF
# Create startup script
RUN cat <<'EOF' > /usr/local/bin/start-openclaw
#!/bin/bash
set -e
mkdir -p /root/.openclaw/{sessions,workspace,plugins,agents/main/sessions,credentials}
ln -s /root/.openclaw/workspace /root/.openclaw/memory || true
chmod 700 /root/.openclaw || true
python3 /usr/local/bin/sync.py restore || true
export OPENCLAW_GATEWAY_TOKEN="${OPENCLAW_GATEWAY_PASSWORD}"
CLEAN_BASE=$(echo "${OPENAI_API_BASE}" | sed "s|/chat/completions||g" | sed "s|/v1/|/v1|g" | sed "s|/v1$|/v1|g")
cat > /root/.openclaw/openclaw.json <<EOC
{
"models": {
"mode": "merge",
"providers": {
"zai": {
"baseUrl": "${CLEAN_BASE}",
"apiKey": "${OPENAI_API_KEY}",
"api": "openai-completions",
"models": [
{"id": "glm-4.7", "name": "GLM-4.7 Coding", "contextWindow": 200000, "maxTokens": 8192},
{"id": "glm-5", "name": "GLM-5", "contextWindow": 200000, "maxTokens": 8192}
]
}
}
},
"agents": {
"defaults": {
"model": {"primary": "zai/glm-4.7"},
"workspace": "~/.openclaw/workspace"
}
},
"gateway": {
"mode": "local", "bind": "lan", "port": ${PORT},
"trustedProxies": ["0.0.0.0/0"],
"auth": { "mode": "token", "token": "${OPENCLAW_GATEWAY_PASSWORD}" },
"controlUi": { "allowInsecureAuth": true }
}
}
EOC
(while true; do sleep 10800; python3 /usr/local/bin/sync.py backup || true; done) &
openclaw doctor --fix || true
exec openclaw gateway run --port ${PORT}
EOF
RUN chmod +x /usr/local/bin/start-openclaw
EXPOSE 7860
CMD ["/usr/local/bin/start-openclaw"] |