Spaces:
Paused
Paused
| # 采用官方给定的核心底座 | |
| ARG HERMES_AGENT_VERSION=latest | |
| FROM nousresearch/hermes-agent:${HERMES_AGENT_VERSION} | |
| USER root | |
| # 1. 完整保留原项目的全部系统依赖 | |
| RUN apt-get update && apt-get install -y --no-install-recommends \ | |
| ca-certificates \ | |
| curl \ | |
| jq \ | |
| sudo \ | |
| python3 \ | |
| python3-venv \ | |
| python3-pip \ | |
| chromium \ | |
| dbus \ | |
| dbus-x11 \ | |
| libnss3 \ | |
| libatk1.0-0 \ | |
| libatk-bridge2.0-0 \ | |
| libdrm2 \ | |
| libgbm1 \ | |
| libxcomposite1 \ | |
| libxdamage1 \ | |
| libxrandr2 \ | |
| libxkbcommon0 \ | |
| libx11-6 \ | |
| libxext6 \ | |
| libxfixes3 \ | |
| fonts-dejavu-core \ | |
| fonts-liberation \ | |
| fonts-noto-color-emoji \ | |
| && (apt-get install -y --no-install-recommends libasound2 2>/dev/null \ | |
| || apt-get install -y --no-install-recommends libasound2t64 2>/dev/null \ | |
| || true) \ | |
| && rm -rf /var/lib/apt/lists/* | |
| # 2. 将 JupyterLab 注入到虚拟环境中以驱动原项目的 Terminal 终端 | |
| RUN uv pip install --python /opt/hermes/.venv/bin/python --no-cache-dir \ | |
| "jupyterlab>=4.0,<5" \ | |
| "tornado>=6.4" \ | |
| "ipywidgets>=8.1" \ | |
| && printf 'hermes ALL=(ALL) NOPASSWD: ALL\n' > /etc/sudoers.d/hermes \ | |
| && chmod 0440 /etc/sudoers.d/hermes \ | |
| && /usr/sbin/visudo -cf /etc/sudoers.d/hermes | |
| # 3. 复制魔改项目的全部核心组件 | |
| COPY start.sh /opt/huggingmes/start.sh | |
| COPY health-server.js /opt/huggingmes/health-server.js | |
| COPY cloudflare-proxy-setup.py /opt/huggingmes/cloudflare-proxy-setup.py | |
| COPY cloudflare-keepalive-setup.py /opt/huggingmes/cloudflare-keepalive-setup.py | |
| COPY env-builder.html /opt/huggingmes/env-builder.html | |
| COPY env-builder.js /opt/huggingmes/env-builder.js | |
| # 4. 去除 Windows 换行符隐患并放开执行权限 | |
| RUN sed -i 's/\r$//' /opt/huggingmes/start.sh && \ | |
| chmod -R 777 /opt/huggingmes | |
| # 5. 保留原项目看板数据库迁移幂等补丁 | |
| RUN python3 - <<'PY' | |
| import sys | |
| try: | |
| from pathlib import Path | |
| p = Path("/opt/hermes/hermes_cli/kanban_db.py") | |
| if not p.exists(): | |
| print("kanban patch: file not found, skipping") | |
| sys.exit(0) | |
| src = p.read_text(encoding="utf-8", errors="replace") | |
| sentinel = "# huggingmes: idempotent-alter" | |
| if sentinel in src: | |
| print("kanban patch: already applied, skipping") | |
| sys.exit(0) | |
| old = ( | |
| ' conn.execute(\n' | |
| ' "ALTER TABLE tasks ADD COLUMN consecutive_failures "\n' | |
| ' "INTEGER NOT NULL DEFAULT 0"\n' | |
| ' )' | |
| ) | |
| new = ( | |
| f' try: {sentinel}\n' | |
| ' conn.execute(\n' | |
| ' "ALTER TABLE tasks ADD COLUMN consecutive_failures "\n' | |
| ' "INTEGER NOT NULL DEFAULT 0"\n' | |
| ' )\n' | |
| ' except Exception:\n' | |
| ' pass' | |
| ) | |
| if old not in src: | |
| print("kanban patch: pattern not found, may be fixed upstream, skipping") | |
| sys.exit(0) | |
| p.write_text(src.replace(old, new), encoding="utf-8") | |
| print("kanban patch: applied") | |
| except Exception as e: | |
| print(f"kanban patch: error ({e}), skipping", file=sys.stderr) | |
| PY | |
| # 确保环境变量 PATH 在全量挂载下正常工作 | |
| RUN echo 'export PATH="/opt/hermes/.venv/bin:/opt/data/.local/bin:$PATH"' \ | |
| > /etc/profile.d/hermes-venv.sh | |
| # 顺应底层用户身份 | |
| USER hermes | |
| # 核心声明:直接将整个存储桶作为唯一的 HERMES_HOME 数据保存地 | |
| ENV HERMES_HOME=/opt/data \ | |
| HUGGINGMES_APP_DIR=/opt/huggingmes \ | |
| HERMES_AGENT_VERSION=${HERMES_AGENT_VERSION} \ | |
| PYTHONUNBUFFERED=1 \ | |
| PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium | |
| EXPOSE 7861 | |
| HEALTHCHECK --interval=30s --timeout=5s --start-period=60s \ | |
| CMD curl -fsS http://localhost:7861/health || exit 1 | |
| # 💥 关键修改:清空基础镜像的 ENTRYPOINT,不再走官方 s6-overlay 流程,彻底屏蔽 chown 权限地雷 | |
| ENTRYPOINT [] | |
| # 直接拉起我们的控制脚本作为 PID 1 独立执行 | |
| CMD ["/bin/bash", "/opt/huggingmes/start.sh"] | |