01:Hello, OpenClaw — 凌晨兩點的 AI 奇遇
當我在凌晨兩點滑著 GitHub 的時候,我沒想到接下來的一個月會是這樣的光景:容器陣亡 9 次,追著一個改了 3 次名字的專案跑,放棄 NAS 改上雲端又繞回來,最後養出兩隻 AI 貓一起工作。
這是建置日誌系列的第一篇。我想先聊聊:一個剛離開製造業的人,為什麼會在深夜搞這些。
一切從 Mac Mini M4 開始
你可能聽過 Mac Mini M4 熱銷的消息。但你知道有一群人買它不是為了剪片、寫程式,而是讓一個 AI Agent 24/7 跑在本機,隨時待命,自動執行任務?
我第一次聽到這概念的反應是:「聽起來不錯,但我哪有錢買 Mac Mini。」
然後我看了一眼角落的 Synology DS920+。
「NAS 不就是台 24/7 不關機的 Linux 主機嗎?Intel J4125 四核心、8GB RAM,應該可以吧?」
當下我做了個決定:不買新機,在 NAS 上搞定。
結果這個決定讓我在接下來 27 小時內見識到什麼叫「可以,但沒那麼簡單」。
你到底叫什麼名字
在 GitHub 上搜尋「AI Agent self-hosted」的時候,我找到一個專案叫 Clawdbot。文件寫得很清楚:Docker 部署、支援 Claude API、有 Web 介面、還能整合 Discord。
就是你了。
docker pull ghcr.io/clawdbot/clawdbot:latest
Docker 很冷靜地回我:
Error response from daemon: manifest for ghcr.io/clawdbot/clawdbot:latest not found
我重新看 README,發現一行小字:The project has been renamed to moltbot。
好,那就 moltbot:
docker pull ghcr.io/moltbot/moltbot:latest
Error: denied: repository does not exist
我去翻 Issues,有人問同樣的問題,作者回覆說已經改回 OpenClaw 了,但映像檔路徑暫時還是 ghcr.io/molt-bot/moltbot。
我看著螢幕深呼吸。這是一個有三個名字的專案——原名 Clawdbot,改名 Moltbot,最終名 OpenClaw,但 Docker 路徑還是 molt-bot。就像你去找一個朋友,門牌寫「王大明」,信箱寫「大明王」,按門鈴他跟你說「我現在叫 Kevin」。
後來我發現,追著 AI 工具改名跑,是這一行的常態。
DS920+:應該可以吧
名字的事先擱著,來談硬體。DS920+ 的規格看起來夠用:J4125 四核心、8GB RAM、DSM 7.2 支援 Docker。我的想法很簡單——OpenClaw 就是個 Node.js 應用加 API 呼叫,NAS 平常也只跑個 Plex,閒著也是閒著。
這個判斷沒錯。但我忽略了一件事:「可以跑」跟「能順利跑起來」是兩回事。Docker 網路設定、NAS 的 UID/GID 權限地獄、瀏覽器沙盒、HTTPS 憑證——每一項單獨看都不難,全部加在一起就是另一回事了。
凌晨 00:07:第一次 denied
我在 Synology 的 Container Manager 裡準備 pull image。GitHub Container Registry 需要認證,所以先申請了 PAT,給 read:packages 權限:
echo $GITHUB_TOKEN | docker login ghcr.io -u kevin --password-stdin
docker pull ghcr.io/molt-bot/moltbot:latest
這次成功了。進度條跑完的時候我以為最難的部分結束了。
凌晨 00:21:MODULE_NOT_FOUND
接著寫 docker-compose.yml,參考官方文件配了一個基本版:
version: '3.8'
services:
moltbot:
image: ghcr.io/molt-bot/moltbot:latest
container_name: moltbot-gateway
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
ports:
- "3000:3000"
volumes:
- ./workspace:/app/workspace
restart: unless-stopped
docker-compose up -d,容器啟動。然後:
moltbot-gateway | Error: Cannot find module '/app/gateway'
moltbot-gateway exited with code 1
進容器看,/app 底下根本沒有 gateway 這個檔案。Dockerfile 的 entrypoint 寫的是 node /app/gateway,但實際的入口是 /app/dist/index.js,要透過 moltbot 指令呼叫。
文件跟程式碼不同步。在開源專案裡這太常見了。
凌晨 00:25:Exit 0,但什麼都沒做
改了 command: gateway 再試。容器沒報錯,但直接退出了,Exit code 0。
看 logs 才發現,它把 gateway 當成參數印了一頁 help 選單,然後優雅地結束程序。禮貌,但沒用。
凌晨 00:30:幽靈容器
這時候 Synology 的介面開始鬧鬼了。容器顯示「執行中」,點開卻說「不存在」,重新整理 ID 又變了。
原因很簡單:容器啟動 → 印 help → Exit 0 → Docker 看到 restart: unless-stopped 就重啟 → 回到開頭。這個循環每三秒跑一次,Synology 的 UI 根本跟不上。
凌晨 00:45:sleep infinity
反覆陣亡四次之後,我用了一個很蠢但保證有效的方法:
command: sleep infinity
讓容器活著,什麼都不做,只是活著。然後手動進去:
docker exec -it moltbot-gateway sh
cd /app
node dist/index.js gateway
OpenClaw Gateway starting...
Listening on port 3000
終於。打開瀏覽器,輸入 http://192.168.1.100:3000,看到了 OpenClaw 的 WebUI。
然後它顯示:Status: Disconnected — Pairing required
好吧,至少容器活著了。sleep infinity 這招確實蠢,但在什麼都不動的時候,讓系統先活著比什麼都重要。後來我在生產環境也用過類似的思路——先穩住,再優化。
凌晨一點的待辦清單
凌晨一點。容器跑起來了,但 Pairing 認證、UID 權限、瀏覽器沙盒、HTTPS 憑證、Webhook 設定,全部還沒搞。
距離「真正能用」還很遠。
但至少,我跟 OpenClaw 正式見面了。
Hello, OpenClaw。雖然你讓我在凌晨陣亡了四次。
Build Log 系列第一篇
→ 下一篇:02:Docker 說再見的第九次 — NAS 上的容器陣亡循環