openclaw / Dockerfile
cnrock's picture
Update Dockerfile
df59f9b verified
# 核心镜像选择
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 \
sqlite3 \
unzip \
curl \
vim \
rclone \
ca-certificates \
chromium \
libnss3 libnspr4 \
libatk1.0-0 libatk-bridge2.0-0 \
libcups2 \
libdrm2 \
libxkbcommon0 \
libxcomposite1 libxdamage1 libxext6 libxfixes3 libxrandr2 \
libgbm1 \
libpango-1.0-0 libcairo2 \
libasound2 \
fonts-noto-cjk fonts-noto-color-emoji \
&& rm -rf /var/lib/apt/lists/*
# 2. 安装 HF 数据交互工具
RUN pip3 install --no-cache-dir huggingface_hub --break-system-packages
# 2) 固定 Playwright 版本,并把浏览器缓存写入镜像层
ARG PLAYWRIGHT_VERSION=1.50.1
ENV PLAYWRIGHT_BROWSERS_PATH=/ms-playwright
ENV CHROME_PATH=/usr/bin/chromium
WORKDIR /app
# 3. 构建环境与 Git 协议优化
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
# 4.1 安装qmd 插件
# 安装 Bun(官方推荐方式)
RUN curl -fsSL https://bun.sh/install | bash
# 添加 Bun 到 PATH(关键步骤!)
ENV BUN_INSTALL="/root/.bun"
ENV PATH="${BUN_INSTALL}/bin:${PATH}"
# 验证 Bun 安装
RUN bun --version
# Install uv for running Python scripts
RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \
mv /root/.local/bin/uv /usr/local/bin/uv && \
mv /root/.local/bin/uvx /usr/local/bin/uvx 2>/dev/null || true
# 5. 环境变量预设
ENV PORT=7860 \
OPENCLAW_GATEWAY_MODE=local \
HOME=/root \
OPENCLAW_GATEWAY_CONTROLUI_ALLOWINSECUREAUTH=true \
OPENCLAW_GATEWAY_TRUSTED_PROXIES="0.0.0.0/0,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,100.64.0.0/10,127.0.0.1/8"
# 如果 /app 没有 package.json,补一个最小的
RUN test -f package.json || (printf '{\n "name": "openclaw-app",\n "private": true\n}\n' > package.json)
# 3) 关键:不用 npm 安装 Playwright(会触发 npm 的奇怪报错),改用 pnpm
# 4) 关键:/app 在这个镜像里被当成 workspace root,所以 pnpm add 需要加 -w
RUN corepack enable \
&& corepack prepare pnpm@9.15.3 --activate \
&& pnpm add -D playwright@${PLAYWRIGHT_VERSION} \
&& pnpm exec playwright install chromium \
&& pnpm exec playwright install-deps chromium
# 6. Python 同步引擎 (sync.py) - 修复热重启问题
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\
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\
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"Success: Restored entire directory from {name}")\n\
return True\n\
except Exception as e: print(f"Restore Error: {e}")\n\
\n\
def backup():\n\
try:\n\
day = datetime.now().strftime("%Y-%m-%d_%H")\n\
name = f"backup_{day}.tar.gz"\n\
tmp_path = f"/tmp/{name}"\n\
base_dir = "/root/.openclaw"\n\
\n\
with tarfile.open(tmp_path, "w:gz") as tar:\n\
if os.path.exists(base_dir):\n\
for item in os.listdir(base_dir):\n\
tar.add(os.path.join(base_dir, item), arcname=item)\n\
\n\
api.upload_file(path_or_fileobj=tmp_path, path_in_repo=name, repo_id=repo_id, repo_type="dataset", token=token)\n\
print(f"Backup {name} Success. All files in {base_dir} included.")\n\
\n\
# 上传完立刻清理临时文件,释放空间\n\
if os.path.exists(tmp_path):\n\
os.remove(tmp_path)\n\
except Exception as e: print(f"Backup Error: {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. 启动控制逻辑(使用 printf 避免 heredoc 问题)
RUN echo '#!/bin/bash\n\
set -e\n\
mkdir -p /root/.openclaw\n\
chmod 700 /root/.openclaw\n\
\n\
python3 /usr/local/bin/sync.py restore\n\
\n\
CLEAN_BASE=$(echo "$OPENAI_API_BASE" | sed "s|/chat/completions||g" | sed "s|/v1/|/v1|g" | sed "s|/v1$|/v1|g")\n\
\n\
# 生成配置 - 使用 printf 避免引号问题\n\
printf '"'"'{\n\
"models": {\n\
"providers": {\n\
"nvidia": {\n\
"baseUrl": "%s", "apiKey": "%s", "api": "openai-completions",\n\
"models": [{ "id": "%s", "name": "z-ai/glm4.7", "contextWindow": 128000 }]\n\
}\n\
}\n\
},\n\
"agents": { "defaults": { "model": { "primary": "nvidia/%s" } } },\n\
"gateway": {\n\
"mode": "local", "bind": "lan", "port": %s,\n\
"trustedProxies": ["0.0.0.0/0", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "127.0.0.1/8"],\n\
"auth": { "mode": "token", "token": "%s" },\n\
"controlUi": { \n\
"enabled": true,\n\
"allowInsecureAuth": true,\n\
"dangerouslyAllowHostHeaderOriginFallback": true,\n\
"dangerouslyDisableDeviceAuth": true\n\
}\n\
}\n\
}\n\
'"'"' "$CLEAN_BASE" "$OPENAI_API_KEY" "$MODEL" "$MODEL" "$PORT" "$OPENCLAW_GATEWAY_PASSWORD" > /root/.openclaw/openclaw.json\n\
\n\
(while true; do sleep 86400; python3 /usr/local/bin/sync.py backup; done) &\n\
\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"]