mypet / Dockerfile
asons's picture
Update Dockerfile
7c32358 verified
# 核心镜像:使用 node-slim 保持轻量
FROM node:22-slim
# 1. 整合系统依赖安装
RUN apt-get update && apt-get install -y --no-install-recommends \
git python3 python3-pip ca-certificates procps tzdata \
build-essential curl \
# 依赖
chromium fonts-noto-cjk-extra fonts-noto-color-emoji \
&& rm -rf /var/lib/apt/lists/*
# 2. 安装 Python 依赖
RUN pip3 install --no-cache-dir huggingface_hub scrapling curl_cffi browserforge html2text ddgs --break-system-packages
# 3. 安装 OpenClaw
RUN npm install -g openclaw@latest @marvae24/weibo-cli --registry=https://registry.npmjs.org/ \
--unsafe-perm=true --foreground-scripts && npm cache clean --force
# 5. 环境变量预设 (✅ 新增 OPENCLAW_SKIP_CANVAS_HOST=1 禁用画板防卡顿)
ENV TZ=Asia/Shanghai \
PORT=7860 \
HOME=/root \
OPENCLAW_TRUST_LOCAL_WS=1 \
OPENCLAW_SECURITY_STRICT=false \
NODE_TLS_REJECT_UNAUTHORIZED=0 \
OPENCLAW_TRUST_PROXY=true \
NODE_ENV=production \
OPENCLAW_SKIP_CANVAS_HOST=1
# 6. 同步引擎 (✅ 优化:去掉了对 MODEL 变量的自动覆盖)
RUN echo 'import os, sys, tarfile, time\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\
base_dir = "/root"\n\
\n\
def restore():\n\
if not repo_id or not token: return\n\
try:\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 = "backup_" + day + ".tar.gz"\n\
if name in files:\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=base_dir)\n\
print("--- [Sync] ✅ 恢复成功: " + day + " ---")\n\
return True\n\
except Exception as e: print("--- [Sync] ❌ 恢复失败: " + str(e))\n\
\n\
def backup():\n\
if not repo_id or not token: return\n\
try:\n\
try:\n\
files = api.list_repo_files(repo_id=repo_id, repo_type="dataset", token=token)\n\
cutoff = datetime.now() - timedelta(days=14)\n\
for f in files:\n\
if f.startswith("backup_") and f.endswith(".tar.gz"):\n\
try:\n\
if datetime.strptime(f[7:17], "%Y-%m-%d") < cutoff:\n\
api.delete_file(path_in_repo=f, repo_id=repo_id, repo_type="dataset", token=token)\n\
print("--- [Sync] 🗑️ 已清理过期备份: " + f + " ---")\n\
except: pass\n\
except Exception as e: print("--- [Sync] ⚠️ 清理检查失败: " + str(e))\n\
\n\
target_dir = "/root/.openclaw"\n\
if not os.path.exists(target_dir): return\n\
day_str = datetime.now().strftime("%Y-%m-%d")\n\
name = "backup_" + day_str + ".tar.gz"\n\
\n\
def exclude_modules(tarinfo):\n\
if "node_modules" in tarinfo.name: return None\n\
return tarinfo\n\
\n\
with tarfile.open(name, "w:gz") as tar: tar.add(target_dir, arcname=".openclaw", filter=exclude_modules)\n\
api.upload_file(path_or_fileobj=name, path_in_repo=name, repo_id=repo_id, repo_type="dataset", token=token)\n\
if os.path.exists(name): os.remove(name)\n\
print("--- [Sync] ✨ 备份完成 (已跳过依赖): " + name + " ---")\n\
except Exception as e: print("--- [Sync] ❌ 备份失败: " + str(e))\n\
\n\
def update_env():\n\
import json\n\
path = "/root/.openclaw/openclaw.json"\n\
if not os.path.exists(path): return\n\
try:\n\
with open(path, "r") as f: c = json.load(f)\n\
b = os.getenv("OPENAI_API_BASE", "").replace("/chat/completions", "").replace("/v1/", "/v1")\n\
k = os.getenv("OPENAI_API_KEY", "")\n\
p = os.getenv("OPENCLAW_GATEWAY_PASSWORD", "")\n\
if "models" in c and "providers" in c["models"] and "custom_provider" in c["models"]["providers"]:\n\
if b: c["models"]["providers"]["custom_provider"]["baseUrl"] = b\n\
if k: c["models"]["providers"]["custom_provider"]["apiKey"] = k\n\
if "gateway" in c and "auth" in c["gateway"]:\n\
if p: c["gateway"]["auth"]["token"] = p\n\
with open(path, "w") as f: json.dump(c, f, indent=2)\n\
print("--- [Sync] 🔄 环境变量已热更新至配置文件 ---")\n\
except Exception as e: print("--- [Sync] ⚠️ 配置文件热更新失败: " + str(e))\n\
\n\
if __name__ == "__main__":\n\
if len(sys.argv) > 1 and sys.argv[1] == "backup": backup()\n\
elif len(sys.argv) > 1 and sys.argv[1] == "update": update_env()\n\
else: restore()' > /usr/local/bin/sync.py
# 7. 最终启动脚本
RUN echo "#!/bin/bash\n\
set -e\n\
mkdir -p /root/.openclaw\n\
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\n\
\n\
python3 /usr/local/bin/sync.py restore\n\
\n\
if ls /root/.openclaw/extensions/*/package.json 1> /dev/null 2>&1; then\n\
for pkg in /root/.openclaw/extensions/*/package.json; do\n\
ext_dir=\$(dirname \"\$pkg\")\n\
echo \"--- [System] 📦 正在重建插件依赖: \$(basename \"\$ext_dir\") ---\"\n\
npm install --prefix \"\$ext_dir\" --production --no-audit --no-fund\n\
done\n\
fi\n\
\n\
find /root/.openclaw -name \"*.lock\" -delete\n\
chmod 700 /root/.openclaw\n\
\n\
if [ ! -f /root/.openclaw/openclaw.json ]; then\n\
echo \"--- [System] 📝 初次运行,生成默认配置... ---\"\n\
CLEAN_BASE=\$(echo \"\$OPENAI_API_BASE\" | sed \"s|/chat/completions||g\" | sed \"s|/v1/|/v1|g\")\n\
cat > /root/.openclaw/openclaw.json <<EOF\n\
{\n\
\"models\": { \
\"providers\": { \
\"custom_provider\": { \
\"baseUrl\": \"\$CLEAN_BASE\", \
\"apiKey\": \"\$OPENAI_API_KEY\", \
\"api\": \"openai-completions\", \
\"models\": [{ \"id\": \"\$MODEL\", \"name\": \"MyModel\", \"contextWindow\": 256000 }] \
} \
} \
},\n\
\"agents\": { \
\"defaults\": { \
\"model\": { \
\"primary\": \"custom_provider/\$MODEL\" \
}, \
\"imageModel\": \"custom_provider/\$MODEL\" \
} \
},\n\
\"gateway\": {\n\
\"mode\": \"local\", \"port\": 7860, \"bind\": \"custom\", \"customBindHost\": \"0.0.0.0\",\n\
\"trustedProxies\": [\"10.0.0.0/8\"],\n\
\"auth\": { \"mode\": \"token\", \"token\": \"\$OPENCLAW_GATEWAY_PASSWORD\" },\n\
\"controlUi\": { \"enabled\": true, \"allowInsecureAuth\": true, \"dangerouslyDisableDeviceAuth\": true, \"dangerouslyAllowHostHeaderOriginFallback\": true, \"allowedOrigins\": [\"https://rickyai365-mypet.hf.space\"] },\n\
\"tools\": { \"deny\": [\"gateway\"] }\n\
}\n\
}\n\
EOF\n\
else\n\
python3 /usr/local/bin/sync.py update\n\
fi\n\
\n\
(while true; do sleep 3600; python3 /usr/local/bin/sync.py backup; done) &\n\
\n\
echo \"--- [System] 🚀 正在启动 OpenClaw Gateway... ---\"\n\
export NODE_ENV=production\n\
export OPENCLAW_TRUST_PROXY=true\n\
\n\
openclaw doctor --fix\n\
exec openclaw gateway run --port 7860\n\
" > /usr/local/bin/start-openclaw && chmod +x /usr/local/bin/start-openclaw
EXPOSE 7860
CMD ["/usr/local/bin/start-openclaw"]