tao-shen commited on
Commit
04264a9
ยท
1 Parent(s): c03793c

perf: node user build (-104s chown), merge RUN layers (-170s), plugin whitelist (-40s)

Browse files
Files changed (3) hide show
  1. Dockerfile +42 -65
  2. openclaw.json +1 -0
  3. scripts/sync_hf.py +2 -1
Dockerfile CHANGED
@@ -1,85 +1,62 @@
1
- # OpenClaw on Hugging Face Spaces โ€” ไปŽๆบ็ ๆž„ๅปบ๏ผˆๅธฆ่ฎกๆ—ถ๏ผ‰
2
- # ๆ–‡ๆกฃ: https://huggingface.co/docs/hub/spaces-sdks-docker
3
-
4
  FROM node:22-bookworm
5
  SHELL ["/bin/bash", "-c"]
6
 
7
- # โ”€โ”€ Step 1: System dependencies โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
8
- RUN echo "[build][step1] Installing system deps..." && START=$(date +%s) \
9
- && apt-get update && apt-get install -y --no-install-recommends git ca-certificates curl python3 python3-pip \
 
10
  && rm -rf /var/lib/apt/lists/* \
11
- && echo "[build][step1] System deps: $(($(date +%s) - START))s"
12
-
13
- # โ”€โ”€ Step 2: Python dependencies โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
14
- RUN echo "[build][step2] Installing huggingface_hub..." && START=$(date +%s) \
15
  && pip3 install --no-cache-dir --break-system-packages huggingface_hub \
16
- && echo "[build][step2] huggingface_hub: $(($(date +%s) - START))s"
17
-
18
- # โ”€โ”€ Step 3: Node tooling โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
19
- RUN echo "[build][step3] Enabling corepack + bun..." && START=$(date +%s) \
20
  && corepack enable \
21
- && curl -fsSL https://bun.sh/install | bash \
22
- && echo "[build][step3] Corepack + Bun: $(($(date +%s) - START))s"
23
- ENV PATH="/root/.bun/bin:${PATH}"
 
 
24
 
25
- # โ”€โ”€ Step 4: Clone OpenClaw โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
 
26
  WORKDIR /app
27
- RUN echo "[build][step4] Cloning OpenClaw..." && START=$(date +%s) \
28
- && git clone --depth 1 https://github.com/openclaw/openclaw.git openclaw \
29
- && echo "[build][step4] Git clone: $(($(date +%s) - START))s"
30
- WORKDIR /app/openclaw
31
 
32
- # โ”€โ”€ Step 5: Apply patches โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
33
- COPY patches /app/patches
34
- RUN echo "[build][step5] Applying patches..." && START=$(date +%s) \
 
 
 
35
  && if [ -f /app/patches/web-inbound-record-activity-after-body.patch ]; then \
36
- patch -p1 < /app/patches/web-inbound-record-activity-after-body.patch; \
 
37
  fi \
38
- && echo "[build][step5] Patches: $(($(date +%s) - START))s"
39
-
40
- # โ”€โ”€ Step 6: pnpm install โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
41
- RUN echo "[build][step6] pnpm install..." && START=$(date +%s) \
42
  && pnpm install --frozen-lockfile \
43
- && echo "[build][step6] pnpm install: $(($(date +%s) - START))s"
44
-
45
- # โ”€โ”€ Step 7: pnpm build โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
46
- RUN echo "[build][step7] pnpm build..." && START=$(date +%s) \
47
  && pnpm build \
48
- && echo "[build][step7] pnpm build: $(($(date +%s) - START))s"
49
-
50
- # โ”€โ”€ Step 8: pnpm ui:build โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
51
- ENV OPENCLAW_PREFER_PNPM=1
52
- RUN echo "[build][step8] pnpm ui:build..." && START=$(date +%s) \
53
- && pnpm ui:build \
54
- && echo "[build][step8] pnpm ui:build: $(($(date +%s) - START))s"
55
-
56
- # โ”€โ”€ Step 9: Verify build artifacts โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
57
- RUN echo "[build][step9] Verifying build artifacts..." \
58
- && test -f dist/entry.js && echo " OK dist/entry.js" \
59
- && test -f dist/plugin-sdk/index.js && echo " OK dist/plugin-sdk/index.js" \
60
- && test -d extensions/telegram && echo " OK extensions/telegram" \
61
- && test -d extensions/whatsapp && echo " OK extensions/whatsapp" \
62
- && test -d dist/control-ui && echo " OK dist/control-ui"
63
-
64
- # โ”€โ”€ Step 10: Inject auto-token into Control UI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
65
  COPY --chown=node:node scripts /home/node/scripts
66
- RUN chmod +x /home/node/scripts/inject-token.sh && bash /home/node/scripts/inject-token.sh
 
 
67
 
68
- # โ”€โ”€ Step 11: Final setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
69
  ENV NODE_ENV=production
70
- RUN mkdir -p /app/openclaw/empty-bundled-plugins
71
  ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/openclaw/empty-bundled-plugins
72
- RUN chown -R node:node /app
73
-
74
- RUN mkdir -p /home/node/.openclaw/workspace /home/node/.openclaw/credentials
75
-
76
- COPY --chown=node:node openclaw.json /home/node/scripts/openclaw.json.default
77
- RUN chmod +x /home/node/scripts/entrypoint.sh \
78
- && chmod +x /home/node/scripts/sync_hf.py \
79
- && chown -R node:node /home/node
80
-
81
- USER node
82
- ENV HOME=/home/node
83
  ENV PATH="/home/node/.local/bin:$PATH"
84
  WORKDIR /home/node
85
 
 
1
+ # OpenClaw on Hugging Face Spaces โ€” ไผ˜ๅŒ–ๆž„ๅปบ๏ผˆv2๏ผ‰
2
+ # ไผ˜ๅŒ–็‚น๏ผšnode ็”จๆˆทๆž„ๅปบ๏ผˆๆถˆ้™ค chown๏ผ‰ใ€ๅˆๅนถ RUN ๅฑ‚๏ผˆๅ‡ๅฐ‘ๅฑ‚ๅผ€้”€๏ผ‰
 
3
  FROM node:22-bookworm
4
  SHELL ["/bin/bash", "-c"]
5
 
6
+ # โ”€โ”€ Layer 1 (root): ็ณป็ปŸไพ่ต– + ๅทฅๅ…ท๏ผˆๅ…จ้ƒจๅˆๅนถไธบไธ€ๅฑ‚๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
7
+ RUN echo "[build][layer1] System deps + tools..." && START=$(date +%s) \
8
+ && apt-get update \
9
+ && apt-get install -y --no-install-recommends git ca-certificates curl python3 python3-pip patch \
10
  && rm -rf /var/lib/apt/lists/* \
 
 
 
 
11
  && pip3 install --no-cache-dir --break-system-packages huggingface_hub \
 
 
 
 
12
  && corepack enable \
13
+ && mkdir -p /app \
14
+ && chown node:node /app \
15
+ && mkdir -p /home/node/.openclaw/workspace /home/node/.openclaw/credentials \
16
+ && chown -R node:node /home/node \
17
+ && echo "[build][layer1] System deps + tools: $(($(date +%s) - START))s"
18
 
19
+ # โ”€โ”€ ๅˆ‡ๆขๅˆฐ node ็”จๆˆท๏ผˆๅŽ็ปญๆ‰€ๆœ‰ๆ“ไฝœ้ƒฝไปฅ node ่บซไปฝ๏ผŒๆ— ้œ€ chown๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
20
+ USER node
21
+ ENV HOME=/home/node
22
  WORKDIR /app
 
 
 
 
23
 
24
+ # โ”€โ”€ Layer 2 (node): Clone + Patch + Install + Build๏ผˆๅˆๅนถไธบไธ€ๅฑ‚๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
25
+ COPY --chown=node:node patches /app/patches
26
+ RUN echo "[build][layer2] Clone + install + build..." && START=$(date +%s) \
27
+ && git clone --depth 1 https://github.com/openclaw/openclaw.git openclaw \
28
+ && echo "[build] git clone: $(($(date +%s) - START))s" \
29
+ && cd openclaw \
30
  && if [ -f /app/patches/web-inbound-record-activity-after-body.patch ]; then \
31
+ patch -p1 < /app/patches/web-inbound-record-activity-after-body.patch \
32
+ && echo "[build] patch applied"; \
33
  fi \
34
+ && T1=$(date +%s) \
 
 
 
35
  && pnpm install --frozen-lockfile \
36
+ && echo "[build] pnpm install: $(($(date +%s) - T1))s" \
37
+ && T2=$(date +%s) \
 
 
38
  && pnpm build \
39
+ && echo "[build] pnpm build: $(($(date +%s) - T2))s" \
40
+ && T3=$(date +%s) \
41
+ && OPENCLAW_PREFER_PNPM=1 pnpm ui:build \
42
+ && echo "[build] pnpm ui:build: $(($(date +%s) - T3))s" \
43
+ && test -f dist/entry.js && echo "[build] OK dist/entry.js" \
44
+ && test -f dist/plugin-sdk/index.js && echo "[build] OK dist/plugin-sdk/index.js" \
45
+ && test -d extensions/telegram && echo "[build] OK extensions/telegram" \
46
+ && test -d extensions/whatsapp && echo "[build] OK extensions/whatsapp" \
47
+ && test -d dist/control-ui && echo "[build] OK dist/control-ui" \
48
+ && mkdir -p /app/openclaw/empty-bundled-plugins \
49
+ && echo "[build][layer2] Total clone+install+build: $(($(date +%s) - START))s"
50
+
51
+ # โ”€โ”€ Layer 3 (node): Scripts + Config + Token ๆณจๅ…ฅ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
 
 
 
 
52
  COPY --chown=node:node scripts /home/node/scripts
53
+ COPY --chown=node:node openclaw.json /home/node/scripts/openclaw.json.default
54
+ RUN chmod +x /home/node/scripts/entrypoint.sh /home/node/scripts/sync_hf.py /home/node/scripts/inject-token.sh \
55
+ && OPENCLAW_APP_DIR=/app/openclaw bash /home/node/scripts/inject-token.sh
56
 
 
57
  ENV NODE_ENV=production
 
58
  ENV OPENCLAW_BUNDLED_PLUGINS_DIR=/app/openclaw/empty-bundled-plugins
59
+ ENV OPENCLAW_PREFER_PNPM=1
 
 
 
 
 
 
 
 
 
 
60
  ENV PATH="/home/node/.local/bin:$PATH"
61
  WORKDIR /home/node
62
 
openclaw.json CHANGED
@@ -38,6 +38,7 @@
38
  }
39
  },
40
  "plugins": {
 
41
  "entries": {
42
  "telegram": {
43
  "enabled": true
 
38
  }
39
  },
40
  "plugins": {
41
+ "allow": ["telegram", "whatsapp"],
42
  "entries": {
43
  "telegram": {
44
  "enabled": true
scripts/sync_hf.py CHANGED
@@ -351,8 +351,9 @@ class OpenClawFullSync:
351
  data["models"]["providers"].pop("gemini", None)
352
  data["agents"]["defaults"]["model"]["primary"] = "openrouter/stepfun/step-3.5-flash:free"
353
 
354
- # Telegram plugin
355
  data.setdefault("plugins", {}).setdefault("entries", {})
 
356
  if "telegram" not in data["plugins"]["entries"]:
357
  data["plugins"]["entries"]["telegram"] = {"enabled": True}
358
  elif isinstance(data["plugins"]["entries"]["telegram"], dict):
 
351
  data["models"]["providers"].pop("gemini", None)
352
  data["agents"]["defaults"]["model"]["primary"] = "openrouter/stepfun/step-3.5-flash:free"
353
 
354
+ # Plugin whitelist (only load telegram + whatsapp to speed up startup)
355
  data.setdefault("plugins", {}).setdefault("entries", {})
356
+ data["plugins"]["allow"] = ["telegram", "whatsapp"]
357
  if "telegram" not in data["plugins"]["entries"]:
358
  data["plugins"]["entries"]["telegram"] = {"enabled": True}
359
  elif isinstance(data["plugins"]["entries"]["telegram"], dict):