Spaces:
Running
Running
File size: 5,877 Bytes
af9e60e d65efac af9e60e 7552177 af9e60e 7552177 d65efac d8ef5a6 af9e60e d65efac 8ba914e af9e60e c26fdc3 c1cd231 af9e60e 2959b7b af9e60e df1c00f af9e60e 8ba914e af9e60e 7cd90ad 765a9cd 64857cd 7cd90ad c26fdc3 d65efac af9e60e c26fdc3 af9e60e d65efac df1c00f af9e60e 7552177 af9e60e 678f3be af9e60e d65efac f41cf76 af9e60e f41cf76 25b14fd 7095f9e e6ee6f1 c07b8ab 64857cd d65efac d5203bf d65efac af9e60e 7552177 af9e60e df1c00f 678f3be af9e60e d65efac f41cf76 af9e60e fe9380c af9e60e | 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 | # ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# π¦ HuggingClaw + π» JupyterLab Terminal
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Port 7861 (exposed): Dashboard + reverse proxy
# / β HuggingClaw dashboard
# /app/ β OpenClaw gateway (internal :7860)
# /terminal/ β JupyterLab terminal (internal :8888)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# ββ Stage 1: Pull pre-built OpenClaw ββ
ARG OPENCLAW_VERSION=latest
FROM ghcr.io/openclaw/openclaw:${OPENCLAW_VERSION} AS openclaw
# ββ Stage 2: Runtime ββ
FROM node:22-slim
ARG OPENCLAW_VERSION=latest
ARG DEV_MODE=false
# DEV_MODE intentionally not baked into runtime ENV β defaults to unset so
# start.sh can auto-enable terminal when GATEWAY_TOKEN is present. Users can
# override by setting DEV_MODE=false as an HF Space Variable to opt out.
# Install system dependencies (+ optional JupyterLab deps in DEV_MODE)
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
sudo \
file \
ca-certificates \
jq \
curl \
dbus \
dbus-x11 \
python3 \
python3-pip \
chromium \
libnss3 \
libatk1.0-0 \
libatk-bridge2.0-0 \
libdrm2 \
libgbm1 \
libxcomposite1 \
libxdamage1 \
libxrandr2 \
libxkbcommon0 \
libx11-6 \
libxext6 \
libxfixes3 \
libasound2 \
fonts-dejavu-core \
fonts-liberation \
fonts-noto-color-emoji \
fonts-freefont-ttf \
fonts-ipafont-gothic \
fonts-wqy-zenhei \
xfonts-scalable \
--no-install-recommends && \
pip3 install --no-cache-dir --break-system-packages huggingface_hub hf_transfer && \
rm -rf /var/lib/apt/lists/*
# Install JupyterLab only when DEV_MODE is enabled (build-time)
# This avoids installing large packages when terminal is not needed
RUN if [ "${DEV_MODE}" = "true" ] || [ "${DEV_MODE}" = "1" ] || [ "${DEV_MODE}" = "yes" ] || [ "${DEV_MODE}" = "on" ]; then \
pip3 install --no-cache-dir --break-system-packages \
jupyterlab==4.5.7 \
tornado==6.5.5 \
ipywidgets==8.1.8 && \
# Copy login template into jupyter_server templates dir
python3 -c "from pathlib import Path; import shutil, jupyter_server; d=Path(jupyter_server.__file__).parent/'templates'; d.mkdir(parents=True,exist_ok=True); shutil.copyfile('/home/node/app/login.html', d/'login.html')" || true; \
fi
# Reuse existing node user (UID 1000). Allow passwordless package-manager
# commands only so runtime apt installs can be replayed after HF Space restarts.
RUN mkdir -p /home/node/app /home/node/.openclaw && \
chown -R 1000:1000 /home/node && \
printf '%s\n' \
'Cmnd_Alias HUGGINGCLAW_APT = /usr/bin/apt, /usr/bin/apt-get, /usr/bin/dpkg' \
'node ALL=(root) NOPASSWD: HUGGINGCLAW_APT' \
> /etc/sudoers.d/huggingclaw-apt && \
chmod 0440 /etc/sudoers.d/huggingclaw-apt && \
visudo -cf /etc/sudoers.d/huggingclaw-apt
# Copy pre-built OpenClaw (skips npm install entirely β much faster!)
COPY --from=openclaw --chown=1000:1000 /app /home/node/.openclaw/openclaw-app
# Add Playwright in an isolated sidecar node_modules
RUN mkdir -p /home/node/browser-deps && \
cd /home/node/browser-deps && \
npm init -y && \
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --omit=dev playwright@1.59.1
# Symlink openclaw CLI so it's available globally
RUN ln -s /home/node/.openclaw/openclaw-app/openclaw.mjs /usr/local/bin/openclaw 2>/dev/null || \
npm install -g openclaw@${OPENCLAW_VERSION}
# Copy HuggingClaw files
COPY --chown=1000:1000 cloudflare-proxy.js /opt/cloudflare-proxy.js
COPY --chown=1000:1000 cloudflare-proxy-setup.py /home/node/app/cloudflare-proxy-setup.py
COPY --chown=1000:1000 health-server.js /home/node/app/health-server.js
COPY --chown=1000:1000 login.html /home/node/app/login.html
COPY --chown=1000:1000 iframe-fix.cjs /home/node/app/iframe-fix.cjs
COPY --chown=1000:1000 start.sh /home/node/app/start.sh
COPY --chown=1000:1000 wa-guardian.js /home/node/app/wa-guardian.js
COPY --chown=1000:1000 cloudflare-keepalive-setup.py /home/node/app/cloudflare-keepalive-setup.py
COPY --chown=1000:1000 openclaw-sync.py /home/node/app/openclaw-sync.py
COPY --chown=1000:1000 multi-provider-key-rotator.cjs /home/node/app/multi-provider-key-rotator.cjs
COPY --chown=1000:1000 env-builder.html /home/node/app/env-builder.html
COPY --chown=1000:1000 env-builder.js /home/node/app/env-builder.js
COPY --chown=1000:1000 jupyter-devdata-sync.py /home/node/app/jupyter-devdata-sync.py
# login.html template is now copied inside the DEV_MODE install block above
RUN chmod +x /home/node/app/start.sh \
/home/node/app/cloudflare-proxy-setup.py \
/home/node/app/cloudflare-keepalive-setup.py \
/home/node/app/openclaw-sync.py \
/home/node/app/jupyter-devdata-sync.py \
/home/node/app/multi-provider-key-rotator.cjs
USER node
ENV HOME=/home/node \
OPENCLAW_VERSION=${OPENCLAW_VERSION} \
PATH=/home/node/.local/bin:/usr/local/bin:$PATH \
NODE_PATH=/home/node/browser-deps/node_modules \
NODE_OPTIONS="--require /opt/cloudflare-proxy.js"
WORKDIR /home/node/app
# 7861 = public entrypoint (dashboard + proxy for both OpenClaw and JupyterLab)
EXPOSE 7861
HEALTHCHECK --interval=30s --timeout=5s --start-period=90s \
CMD curl -fsS http://localhost:7861/health || exit 1
CMD ["/home/node/app/start.sh"]
|