Spaces:
Paused
Paused
File size: 5,336 Bytes
0327b2d a698e3c 0327b2d 542f705 0327b2d a698e3c 1b78e42 0327b2d a698e3c 0327b2d a698e3c 0327b2d a698e3c 0327b2d a698e3c 0327b2d 542f705 0327b2d 527c7a0 0327b2d 527c7a0 1b78e42 a698e3c 0327b2d a698e3c 1b78e42 a698e3c 1b78e42 0e23f2f 0327b2d a698e3c 0e23f2f 1b78e42 0e23f2f a698e3c 1b78e42 a698e3c 0e23f2f a698e3c 1b78e42 a698e3c 1b78e42 542f705 a698e3c 1b78e42 542f705 a698e3c 0e23f2f 0327b2d 0e23f2f a698e3c 542f705 0e23f2f a698e3c 542f705 1b78e42 0e23f2f 1b78e42 0327b2d 527c7a0 a698e3c 0327b2d 1b78e42 | 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 python:3.11-slim
# 基础环境变量,主目录改为 /home/hermes
ENV HERMES_HOME=/home/hermes
ENV PATH="${HERMES_HOME}/.local/bin:${HERMES_HOME}/.npm-global/bin:${PATH}"
ENV NPM_CONFIG_PREFIX="${HERMES_HOME}/.npm-global"
ENV PIP_USER=1
ENV PYTHONUSERBASE="${HERMES_HOME}/.local"
ENV CAMOUFOX_PORT=9377
ENV TZ=Asia/Shanghai
# 系统依赖(完整)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl wget git ca-certificates gnupg \
build-essential gcc g++ make cmake pkg-config \
python3-dev libffi-dev libssl-dev \
ffmpeg ripgrep \
portaudio19-dev libsndfile1-dev libpulse-dev \
libjpeg-dev libpng-dev libtiff-dev libwebp-dev \
libmagic-dev \
libnss3 libnspr4 libatk1.0-0t64 libatk-bridge2.0-0t64 \
libcups2t64 libdrm2 libdbus-1-3 libxkbcommon0 \
libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
libgbm1 libpango-1.0-0 libcairo2 libasound2t64 \
libatspi2.0-0t64 libwayland-client0 libgtk-3-0 \
libdbus-glib-1-2 libxss1 \
xterm fonts-noto-color-emoji fonts-wqy-microhei \
fonts-dejavu-core fontconfig \
tzdata procps htop vim less netcat-openbsd \
&& rm -rf /var/lib/apt/lists/*
# 时区
RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && echo "${TZ}" > /etc/timezone
# Node.js 24
RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
&& apt-get install -y nodejs \
&& rm -rf /var/lib/apt/lists/*
# 创建 hermes 用户(家目录为 /home/hermes)及所有子目录
RUN useradd -m -d ${HERMES_HOME} -s /bin/bash hermes \
&& mkdir -p ${HERMES_HOME}/projects \
&& mkdir -p ${HERMES_HOME}/.local/bin \
&& mkdir -p ${HERMES_HOME}/.npm-global \
&& mkdir -p ${HERMES_HOME}/.cache/camoufox \
&& mkdir -p ${HERMES_HOME}/.hermes \
&& mkdir -p ${HERMES_HOME}/.hermes-web-ui \
&& chown -R hermes:hermes ${HERMES_HOME}
# 切换到 hermes 用户
USER hermes
WORKDIR ${HERMES_HOME}
# 安装 uv,克隆并安装 hermes-agent
RUN pip install --user uv
RUN git clone https://github.com/NousResearch/hermes-agent.git ${HERMES_HOME}/projects/hermes-agent
WORKDIR ${HERMES_HOME}/projects/hermes-agent
RUN pip install --user -e .
RUN pip install --user -e ".[all]" || \
(echo "=== [all] install failed, trying subsets ===" && \
pip install --user -e ".[browser]" && \
pip install --user -e ".[voice]" && \
pip install --user -e ".[search]" && \
pip install --user -e ".[messaging]" && \
echo "=== Subset install completed ===")
WORKDIR ${HERMES_HOME}
RUN pip install --user camoufox[geoip]
RUN npm install -g npm@latest hermes-web-ui
# 软链接
RUN ln -sf ${HERMES_HOME}/.local/bin/hermes ${HERMES_HOME}/.local/bin/hermes-agent \
&& ln -sf ${HERMES_HOME}/.npm-global/bin/hermes-web-ui ${HERMES_HOME}/.local/bin/hermes-web-ui
# 切回 root 打包并放置启动脚本
USER root
# 打包 /home/hermes 目录,压缩包放在根下
RUN tar czf /hermes.tar.gz -C /home hermes
# 启动脚本(路径全部使用 /home/hermes)
RUN cat > /usr/local/bin/start.sh << 'SCRIPT_EOF'
#!/bin/bash
set -e
HERMES_HOME=/home/hermes
# 动态时区
if [ -n "${TZ}" ]; then
echo "Setting timezone to ${TZ}..."
ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime 2>/dev/null || \
echo "Warning: Cannot change timezone (permission denied). Using default."
echo "${TZ}" > /etc/timezone 2>/dev/null || true
fi
echo "=== Hermes Full Stack Container ==="
echo "Timezone: $(cat /etc/timezone 2>/dev/null || echo 'unknown')"
echo "Node.js version: $(node --version)"
echo "npm version: $(npm --version)"
# 首次挂载检测:若 /home/hermes/.local 目录为空则解压
if [ ! -d "${HERMES_HOME}/.local" ] || [ -z "$(ls -A ${HERMES_HOME}/.local 2>/dev/null)" ]; then
echo ">>> Initializing ${HERMES_HOME} from built-in archive..."
tar xzf /hermes.tar.gz -C /home
chown -R hermes:hermes ${HERMES_HOME}
echo ">>> Extraction complete."
fi
# 确保必要目录
mkdir -p ${HERMES_HOME}/.hermes ${HERMES_HOME}/.hermes-web-ui ${HERMES_HOME}/.cache/camoufox
# 环境
export PATH="${HERMES_HOME}/.local/bin:${HERMES_HOME}/.npm-global/bin:${PATH}"
# 确定 hermes 命令
if [ -x "${HERMES_HOME}/projects/hermes-agent/hermes" ]; then
HERMES_CMD="${HERMES_HOME}/projects/hermes-agent/hermes"
else
HERMES_CMD="hermes"
fi
# 首次设置 Agent
if [ ! -f "${HERMES_HOME}/.hermes/config.yaml" ]; then
echo "First startup — initializing Hermes Agent..."
$HERMES_CMD setup --non-interactive || true
fi
# 提示 Camoufox 浏览器
if [ ! -f "${HERMES_HOME}/.local/bin/camoufox" ]; then
echo "=========================================="
echo " Camoufox browser not found."
echo " Install manually in container:"
echo " python -m camoufox fetch"
echo "=========================================="
fi
echo "Starting Hermes Web UI on port ${PORT:-8648}..."
# 后台启动(不退出)
hermes-web-ui start --port ${PORT:-8648}
sleep 2
echo "Dashboard URL: http://localhost:${PORT:-8648}"
# 保活
echo "Container stay-alive mode..."
exec tail -f /dev/null
SCRIPT_EOF
RUN chmod +x /usr/local/bin/start.sh
EXPOSE 8648 9377
VOLUME ["/home/hermes"]
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8648/health || exit 1
ENTRYPOINT ["/usr/local/bin/start.sh"] |