02:Docker 說再見的第九次 — NAS 上的容器陣亡循環
「當你的 Docker 容器第 9 次對你說再見,你會開始思考人生。」
上一篇提到,我成功讓 OpenClaw 的容器用 sleep infinity 活了下來。但這只是「活著」,不是「能用」。
接下來的 12 小時,我經歷了 9 次容器陣亡、3 次 PowerShell 崩潰、無數次的「無法辨識」。
這是在 NAS 上跑 AI Agent 的血淚紀錄。
陣亡 #1-#3:MODULE_NOT_FOUND 的三種姿態
陣亡 #1:entrypoint 設定錯誤
凌晨 1 點,我嘗試修正 docker-compose.yml:
services:
moltbot:
entrypoint: ["node"]
command: ["/app/gateway"]啟動。
Error: Cannot find module '/app/gateway'嗯,因為 /app/gateway 不是 node 模組,是一個不存在的檔案。
陣亡 #2:command 只寫 gateway
改成:
entrypoint: ["moltbot"]
command: ["gateway"]啟動。
Usage: moltbot <command> [options]
Container exited with code 0它又顯示 help 選單了。
陣亡 #3:npx 找不到執行檔
再改:
command: npx moltbot gateway啟動。
could not determine executable to runnpx 說它不知道要執行什麼。
這三次陣亡的共同點:我在猜路徑。我不知道 OpenClaw 的實際執行檔在哪,只能從錯誤訊息裡拼湊。
陣亡 #4:Permission Denied — 權限地獄的開端
既然 Docker 內部的路徑這麼複雜,我決定先進到容器裡手動執行:
docker exec -it moltbot-gateway sh
cd /app
ls -la看到檔案列表:
drwxr-xr-x 2 root root 4096 Jan 28 00:00 dist
drwxr-xr-x 2 root root 4096 Jan 28 00:00 node_modules
-rwxr-xr-x 1 root root 1234 Jan 28 00:00 package.json都是 root 權限,應該沒問題吧?
然後我嘗試執行:
node dist/index.js gateway結果:
Error: EACCES: permission denied, open '/app/workspace/.openclaw/gateway.db'明明是 root,為什麼會 permission denied?
問題出在 volume 掛載。我的 docker-compose.yml 裡有:
volumes:
- ./workspace:/app/workspace在 Synology 上,./workspace 目錄的擁有者是 UID 1026(NAS 帳號),但容器裡的 process 用的是 UID 1000 或 root。權限不匹配。
在 NAS 上跑 Docker,權限問題永遠是第一道關卡。
陣亡 #5-#7:Windows PowerShell 的三連擊
此時我開始懷疑是不是 NAS 環境太複雜了,決定先在 Windows 上測試,至少拿到一個能用的 setup-token。
打開 PowerShell,輸入:
npm install -g moltbotadded 1 package in 1s
done然後:
moltbot setup-tokenmoltbot : 無法辨識 'moltbot' 詞彙是 Cmdlet、函數、指令檔或可執行程式的名稱。
請檢查名稱拼字是否正確,如果包含路徑的話,請確認路徑是否正確,然後再試一次。陣亡 #5:PowerShell 找不到全域安裝的指令。
陣亡 #6:npx 的「無法判斷」
好,那用 npx:
npx moltbot setup-tokencould not determine executable to runnpx 也不行。
陣亡 #7:手動找到執行檔,但參數消失了
此時我開始手動翻 npm 的全域安裝路徑:
$npmRoot = npm root -g
ls "$npmRoot\moltbot"找到了 dist/index.js,直接執行:
node "$npmRoot\moltbot\dist\index.js" setup-token結果:
hello, moltbot然後呢?沒有然後了。程式印了一句 hello, moltbot,就結束了。它沒有接收到 setup-token 參數。
Windows 的 npm 全域安裝加上 PowerShell 的路徑解析,就是一場災難。
凌晨 2 點:「對的森林,但走錯了路徑」
此時我停下來,重新梳理問題:
- Docker 容器裡的 entrypoint 設定不對
- NAS 的權限問題(UID 1026 vs 1000)
- Windows 的 npm 全域安裝找不到指令
- npx 無法判斷執行檔
- 手動執行時參數無法傳遞
每個問題單獨看都有解法,但全部加在一起,我根本不知道該先解決哪一個。
那種感覺就像:你知道家在前面,但一直在隔壁社區繞圈圈。
早上 8 點:sleep infinity 維護模式
經過一夜的折騰,我決定採用一個非常蠢的策略:讓容器活著,什麼都不做,然後手動進去執行指令。
services:
moltbot:
image: ghcr.io/molt-bot/moltbot:latest
command: sleep infinity
volumes:
- ./workspace:/app/workspace
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}然後:
docker exec -it moltbot sh
cd /app
export ANTHROPIC_API_KEY=sk-ant-...
node dist/index.js gateway這次成功了。
OpenClaw Gateway starting...
✓ Pairing code: ABC-123-XYZ
Listening on http://localhost:3000但這個方法的問題很明顯:每次容器重啟都要手動執行、無法自動化、沒有 restart policy、logs 不會自動收集。
這不是「部署」,這是「維護模式」。不過至少,容器活著了。
中午 12 點:陣亡 #8 與 #9
就在我以為「至少有個能跑的版本」的時候——
陣亡 #8:healthcheck 導致認證清除
我嘗試加上 healthcheck 設定:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3結果 Gateway 重新啟動,然後 WebUI 顯示:
disconnected (1008): pairing required我剛才才 pairing 過,怎麼又要重來?原來 healthcheck 導致容器重啟,清空了認證資訊。只好重新執行 openclaw pairing approve web ABC-123-XYZ。
陣亡 #9:瀏覽器沙盒的最後一根稻草
好,pairing 完成了,我嘗試在 OpenClaw 裡執行一個簡單的 web search。
Error: Failed to launch browser
Error: Browser closed with signal SIGTRAPChrome/Playwright 在 Docker 容器裡的經典問題。要解決,需要安裝完整的 Chrome 依賴(libX11, libgbm, libasound…)、設定 --no-sandbox、可能還需要 --disable-dev-shm-usage。
而這些,在 Synology DSM 的 Docker 環境裡非常難搞。
下午 1 點:暫時放棄 NAS
看著螢幕上的錯誤訊息,我做了一個決定:也許 NAS 不是最適合的平台。
不是 DS920+ 效能不夠,而是整個環境的複雜度加起來——Docker 網路設定、權限問題、瀏覽器沙盒、HTTPS 憑證、Port forwarding——每一項都能解決,但全部加在一起,投入的時間成本已經超過「買一台 Mac Mini」了。
更重要的是:我只是想要一個能用的 AI Agent,不是想研究 Docker 底層原理。
陣亡統計:9 次容器之死
| # | 錯誤 | 原因 |
|---|---|---|
| 1 | MODULE_NOT_FOUND |
entrypoint 路徑錯誤 |
| 2 | 顯示 help 後退出 | command 參數未傳遞 |
| 3 | could not determine executable |
npx 找不到執行檔 |
| 4 | EACCES: permission denied |
UID 不匹配(1026 vs 1000) |
| 5 | 無法辨識 'moltbot' |
PowerShell 找不到全域指令 |
| 6 | could not determine executable |
npx 在 Windows 上失效 |
| 7 | hello, moltbot 然後結束 |
參數未傳遞給程式 |
| 8 | disconnected (1008) |
healthcheck 觸發重啟,認證清除 |
| 9 | Browser closed with SIGTRAP |
瀏覽器沙盒無法啟動 |
9 次陣亡,9 種不同的死法。但每一次,都讓我更了解 OpenClaw 的運作方式。
教訓:「可以跑」不等於「能順利跑起來」
DS920+ 的硬體規格完全足夠跑 OpenClaw。問題不在硬體,在於:
- Docker 環境的複雜度:NAS 的 Docker 不等於一般 Linux 的 Docker
- 權限管理:DSM 的 UID/GID 跟容器內部的權限不匹配
- 瀏覽器沙盒:需要完整的 GUI 依賴,不是所有 Docker 環境都有
- HTTPS/Webhook:需要公開的 SSL 憑證,純內網不夠
每一項單獨看都能解決,但全部加在一起,投入的時間成本已經不划算。
Build Log 系列
← 上一篇:01:Hello, OpenClaw
→ 下一篇:03:策略轉折