跳到內容

Docker 安裝指南

適用版本:v1.8.23+ 最後更新:2026-04-22

本指南涵蓋以 Docker Compose 部署 DuDuClaw 伺服器的完整流程 —— 從 port 設定、三大 CLI(Claude / Codex / Gemini)的驗證方式, 到資料持久化、channel webhook 與自動更新。

若只是想在本機試跑,請先參考 docs/deployment-guide.md §1 的原生安裝方式;原生安裝通常啟動更快、除錯更簡單。 Docker 適合伺服器部署、隔離執行環境、或需要統一環境的團隊。


DuDuClaw 的 Docker 映像建置於 container/Dockerfile.server,採三階段建置:

Stage 內容
1. frontend-builder node:22-slim + 建置 React/TS 前端
2. rust-builder rust:slim + 編譯 duduclaw release 二進位
3. production python:3.12-slim + 三大 AI CLI + Docker CLI + 執行期

最終映像內建:

  • duduclaw 主程式(Rust,含 dashboard)
  • @anthropic-ai/claude-code@openai/codex@google/gemini-cli(透過 npm i -g
  • docker.io CLI(用於呼叫宿主機 Docker daemon 建立 agent sandbox)
  • (選用)Python 3.12:僅進階本地推論(MLX / LLMLingua-2,需 mlx_lm / llmlingua)才需要;Skill 安全掃描與通道回覆已是 Rust-native,不再依賴 Python

項目 版本 備註
Docker Engine ≥ 24.0 Linux 建議直接裝原生版;macOS / Windows 用 Docker Desktop 或 Colima
Docker Compose v2.20+ 內建於現代 Docker;指令為 docker compose,非舊的 docker-compose
Git 任意 Clone 原始碼用
磁碟空間 ≥ 4 GB 建置期間會暫用 ~3 GB;成品映像約 ~1.2 GB
Port 18789 預設 gateway port,可改

若要讓 channel webhook(LINE、WhatsApp、Feishu、Generic Webhook)能收到外部訊息, 還需要一個 公開 HTTPS URL。最簡單的方案是 Tailscale FunnelCloudflare Tunnel


終端機視窗
# 1. Clone 原始碼
git clone https://github.com/zhixuli0406/DuDuClaw.git
cd DuDuClaw
# 2. 建立 .env(依需求填入)
cp .env.example .env
$EDITOR .env
# 3. 啟動
docker compose up -d
# 4. 檢視啟動日誌
docker compose logs -f duduclaw
# 5. 驗證
curl http://localhost:18789/health
# {"status":"ok","version":"1.8.23", ...}
# 6. 開啟 Dashboard
open http://localhost:18789

首次啟動時 server-entrypoint.sh 會偵測到 ~/.duduclaw/config.toml 不存在,自動執行 duduclaw onboard --yes 產生基本設定檔(加密儲存 API key 與 channel token)。


docker-compose.yml 只會讀取已定義的變數,缺少的變數會傳入空字串 (因為都用 ${VAR:-} 語法)。下方清單按用途分組。

4.1 Runtime 認證(任選其一以上)

Section titled “4.1 Runtime 認證(任選其一以上)”
變數 用途 備註
CLAUDE_CODE_OAUTH_TOKEN Claude Code 長效 token claude setup-token 產生,推薦,適合無瀏覽器的容器環境
ANTHROPIC_API_KEY Claude API key Fallback,按量計費
OPENAI_API_KEY Codex / OpenAI-compat API key Fallback;ChatGPT Plus/Pro OAuth 走 volume
GEMINI_API_KEY Gemini API key Fallback;Google OAuth 走 volume

至少需要其中一組可用。DuDuClaw 會依 agent.toml [runtime][model] api_mode 決定使用哪一個。詳見 §6 三大 CLI 驗證設定

變數 Channel
LINE_CHANNEL_TOKEN / LINE_CHANNEL_SECRET LINE Messaging API
TELEGRAM_BOT_TOKEN Telegram Bot
DISCORD_BOT_TOKEN Discord Bot
SLACK_BOT_TOKEN / SLACK_APP_TOKEN Slack Socket Mode
WHATSAPP_ACCESS_TOKEN WhatsApp Cloud API(見 .env.example
FEISHU_APP_ID / FEISHU_APP_SECRET 飛書

只需要填入你實際會用到的 channel。沒填的變數不會啟動對應 channel。

docker-compose.yml 目前只預設注入 LINE_* / TELEGRAM_* / DISCORD_* 三組 env var。其他 channel 若要透過 env var 傳入,需自行在 compose 檔案的 environment: 區塊新增;或啟動後改走 Dashboard → Channels → Add 做熱新增(推薦,無須重啟 gateway,token 也會立即加密寫入 config)。

變數 預設 說明
DUDUCLAW_BIND 0.0.0.0 Gateway 監聽位址。容器內必須 0.0.0.0 外部才打得到
DUDUCLAW_ALLOWED_ORIGINS (空) Dashboard WebSocket/CORS 的額外允許 Origin,逗號分隔。透過 tailnet/反向代理網域開 dashboard 且 WS 被 403 時填這裡(見 §13 疑難排解)。與 config.toml [gateway] allowed_origins 合併

Port 在 compose 檔內而非 env var,詳見 §5 Port 設定詳解

變數 用途
TS_AUTHKEY Tailscale Funnel 開機自動加入 tailnet(搭配 --profile tailscale

docker-compose.yml

services:
duduclaw:
ports:
- "18789:18789" # HOST:CONTAINER
environment:
- DUDUCLAW_BIND=0.0.0.0
  • 容器內部:gateway 永遠綁在 0.0.0.0:18789,這是寫死的設計, 因為容器本身就是隔離網路空間,綁 localhost 會變成外部無法存取。
  • 宿主機18789:18789 把宿主機 18789 轉送到容器 18789。

最常見情境是 18789 被佔用或需要多實例。只改左側數字即可:

ports:
- "28789:18789" # 外部改走 28789

之後 dashboard 與 webhook URL 都要改用新 port:

終端機視窗
curl http://localhost:28789/health

右側 18789(容器內部 port)不要動。改它需要同步改 ~/.duduclaw/config.toml[gateway] port, 而 entrypoint 用的是 --yes 自動生成,維護成本較高。

預設 ports: "18789:18789" 會綁 0.0.0.0,區網內其他機器也能連。 若只想本機用(例如搭配反向代理):

ports:
- "127.0.0.1:18789:18789"

兩份 DuDuClaw 跑在同一台機器:

終端機視窗
# 目錄 A — 正式
cd /srv/duduclaw-prod
# ports: "18789:18789"
docker compose up -d
# 目錄 B — 測試
cd /srv/duduclaw-staging
# ports: "28789:18789"
# container_name 也要改,避免衝突
docker compose up -d

記得同步改 container_name(預設 duduclaw-server)避免名稱碰撞。


三個 runtime 各有兩條認證路徑:OAuth(免額外費用,走訂閱方案) 或 API Key(按量付費 fallback)。實務建議「至少裝 OAuth, 並留一把 API Key 當保險」。

容器內三個 OAuth 狀態目錄都有獨立 named volume:

路徑 Volume CLI
/home/duduclaw/.claude duduclaw-claude Claude Code
/home/duduclaw/.codex duduclaw-codex Codex
/home/duduclaw/.gemini duduclaw-gemini Gemini

這代表 登入一次後即使容器重建也不需重登

Claude Code 專為自動化場景提供一個長效 token,不需要瀏覽器回呼, 適合容器 / CI / headless server:

終端機視窗
# 在你「有瀏覽器」的本機電腦上執行(不是容器內)
npm install -g @anthropic-ai/claude-code
claude setup-token
# 依提示完成瀏覽器 OAuth
# 最後會顯示 CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-...

把產生的 token 寫入 .env

.env
CLAUDE_CODE_OAUTH_TOKEN=sk-ant-oat01-xxxxxxxx...

然後:

終端機視窗
docker compose up -d

DuDuClaw 啟動時會讀取環境變數,claude CLI 認得這個 token 就會自動登入,不需要進入容器做任何事。Token 有效期 30 天, 過期前 7 天 DuDuClaw 會在 dashboard 顯示警示。

若你有 Pro / Team / Max 訂閱且想用訂閱 quota:

終端機視窗
# 進入容器
docker compose exec duduclaw bash
# 在容器內執行
claude auth login
# 會顯示一個 URL,在本機瀏覽器打開並完成授權
# 狀態會寫入 /home/duduclaw/.claude/ ── 即 duduclaw-claude volume
# 驗證
claude auth status
exit

容器重啟後狀態仍在(因為 volume)。

.env

終端機視窗
ANTHROPIC_API_KEY=sk-ant-...

這條路徑會按量計費,適合當訂閱用盡或帳號被 rate-limit 時的保險。 DuDuClaw 的 AccountRotator 會自動在多個帳號間輪替,詳見 features/07-account-rotation.md

終端機視窗
docker compose exec duduclaw bash
codex login
# 輸入 ChatGPT 帳號密碼或跟著瀏覽器流程走
# 狀態寫入 /home/duduclaw/.codex/ ── 即 duduclaw-codex volume
exit

此方法使用 ChatGPT 訂閱 quota,無額外 API 費用。

.env

終端機視窗
OPENAI_API_KEY=sk-proj-...

按量計費(OpenAI API 定價)。

終端機視窗
docker compose exec duduclaw bash
gemini auth
# 依提示在本機瀏覽器完成 Google 登入
# 狀態寫入 /home/duduclaw/.gemini/ ── 即 duduclaw-gemini volume
exit

Google 對 Gemini CLI 目前提供免費額度,適合日常使用。

.env

終端機視窗
GEMINI_API_KEY=AIza...

按 Google AI Studio 定價計費。

每個 agent 可以在自己的 agent.toml 指定要用哪個 runtime:

~/.duduclaw/agents/my-agent/agent.toml
[runtime]
preferred = "claude" # 主 runtime:claude / codex / gemini / openai-compat
fallback = "gemini" # Claude 不可用時自動切換

完整範例與 failover 策略請見 features/13-multi-runtime.md

未指定時,RuntimeRegistry 啟動掃描 PATH 後挑選第一個可用的 runtime。

終端機視窗
docker compose exec duduclaw bash
# 三個都應該印出版本
claude --version
codex --version
gemini --version
# Claude 登入狀態
claude auth status

docker-compose.yml 宣告了四個 named volume:

Volume 內容 備份建議
duduclaw-data 主程式資料:config、agents、memory SQLite、logs、bus_queue.jsonl 最重要,建議每日備份
duduclaw-claude Claude CLI OAuth state 中等,遺失需重新 claude auth login
duduclaw-codex Codex OAuth state 中等
duduclaw-gemini Gemini OAuth state 中等

以及掛入的宿主機路徑:

路徑 用途 必要性
/var/run/docker.sock 讓容器呼叫宿主機 Docker daemon 建立 agent sandbox 必要,用於 container sandbox 隔離執行
終端機視窗
# 備份主資料到 tar.gz
docker run --rm \
-v duduclaw_duduclaw-data:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/duduclaw-data-$(date +%F).tar.gz -C /source .

把備份放到目標機,還原到同名 volume:

終端機視窗
docker volume create duduclaw_duduclaw-data
docker run --rm \
-v duduclaw_duduclaw-data:/target \
-v $(pwd):/backup \
alpine tar xzf /backup/duduclaw-data-2026-04-22.tar.gz -C /target

若想方便直接瀏覽資料,可把 named volume 換成 bind mount:

volumes:
- ./data/duduclaw:/home/duduclaw/.duduclaw
- ./data/claude:/home/duduclaw/.claude
- ./data/codex:/home/duduclaw/.codex
- ./data/gemini:/home/duduclaw/.gemini
- /var/run/docker.sock:/var/run/docker.sock

注意宿主機目錄的 owner 必須是 UID 1000(容器內 duduclaw 使用者):

終端機視窗
mkdir -p data/{duduclaw,claude,codex,gemini}
sudo chown -R 1000:1000 data/

路徑 用途 HTTP 200 條件
/health 完整狀態(JSON) 永遠回 200 + 結構化內容
/health/ready Readiness probe agents 已全部載入
/health/live Liveness probe process 還活著

Compose 預設用 /health 做 healthcheck(每 30s,3 次失敗標 unhealthy)。

終端機視窗
# Container 狀態
docker compose ps
# 即時 log
docker compose logs -f duduclaw
# 最近 100 行
docker compose logs --tail=100 duduclaw
# Healthcheck 歷史
docker inspect duduclaw-server --format '{{json .State.Health}}' | jq

Gateway 提供 GET /metrics 端點,指標清單見 docs/deployment-guide.md §8


docker-compose.yml 已內建 Watchtower 服務,每小時檢查一次映像更新。

注意:目前 compose 檔的 WATCHTOWER_SCOPE=duduclaw 設定 只會更新帶有對應 label 的容器,但 duduclaw 服務本身 未設定該 label。若要啟用自動更新,請於 services.duduclaw 加上:

labels:
- "com.centurylinklabs.watchtower.scope=duduclaw"

或移除 WATCHTOWER_SCOPE(會更新所有容器,範圍較大)。

若不想自動更新,直接移除 watchtower 服務區塊即可。


LINE / WhatsApp / Feishu / Generic Webhook 都需要可從網際網路存取的 HTTPS URL 才能收到訊息。若你的 DuDuClaw 跑在家用網路或沒有公網 IP 的伺服器, 常用方案:

方案 適用情境 成本 指引
Tailscale Funnel 家用 / 開發 / 臨時 免費 §11
Cloudflare Tunnel 長期生產 免費(需自有網域) deployment-guide §4
ngrok 快速 demo 免費版 URL 會變 deployment-guide §3
反向代理(Caddy / Nginx) 自有公網 IP + 網域 需自行維護 deployment-guide §5

11. Tailscale Funnel(公開 HTTPS 給 webhook)

Section titled “11. Tailscale Funnel(公開 HTTPS 給 webhook)”

Compose 已附帶 Tailscale 服務,預設在 tailscale profile 下,不自動啟動。

終端機視窗
# 1. 從 Tailscale admin console 產生 auth key
# https://login.tailscale.com/admin/settings/keys
# 建議勾選 "Reusable" + "Ephemeral"
# 2. 寫入 .env
echo "TS_AUTHKEY=tskey-auth-xxxxxxx" >> .env
# 3. 啟動 tailscale profile
docker compose --profile tailscale up -d
# 4. 在 Tailscale admin console 對此機器啟用 Funnel
# Machines → duduclaw → Enable Funnel
# 5. 取得 https URL
docker compose exec tailscale tailscale funnel status
# https://duduclaw.your-tailnet.ts.net/ ← 這就是 webhook 前綴

LINE webhook URL 填 https://duduclaw.your-tailnet.ts.net/webhook/line

Tailscale container 目前使用 image: tailscale/tailscale:latest, 生產環境建議改 pin 到特定 digest(compose 檔已標註 TODO)。


終端機視窗
# 啟動 / 停止 / 重啟
docker compose up -d
docker compose down # 停止並移除 container(volume 不會刪)
docker compose restart duduclaw
# 重新建置映像(程式碼或 Dockerfile 變更後)
docker compose build --no-cache duduclaw
docker compose up -d
# 進入容器 shell
docker compose exec duduclaw bash
# 跑一次性指令
docker compose exec duduclaw duduclaw agent list
docker compose exec duduclaw duduclaw cost summary
# Log
docker compose logs -f duduclaw
docker compose logs --since 1h duduclaw
# 清理
docker compose down -v # ⚠️ 連 volume 一起刪 ── 資料全失
docker system prune -af # ⚠️ 清掉所有未使用 image / container

容器起來但 curl localhost:18789/health 回 Connection refused

Section titled “容器起來但 curl localhost:18789/health 回 Connection refused”

成因:Gateway 綁在容器內部 localhost,宿主機打不到。 檢查

終端機視窗
docker compose exec duduclaw env | grep DUDUCLAW_BIND
# 必須是 DUDUCLAW_BIND=0.0.0.0

若是空字串,把 compose 檔的 environment: 區塊補上即可。

docker compose up 卡在 Compiling duduclaw-gateway

Section titled “docker compose up 卡在 Compiling duduclaw-gateway”

Rust 編譯很吃 CPU/RAM,首次建置在一般筆電上約需 10-20 分鐘。 後續變更會走 incremental cache,通常 1-2 分鐘。

若記憶體不足(< 4 GB)可能會 OOM killed,建議:

  • 改用 pre-built image(若有提供)
  • 或在宿主機預先 cargo build --release 產出二進位,改寫 Dockerfile 直接 COPY(進階)

檢查順序

終端機視窗
# 1. Env var 有沒有傳進去
docker compose exec duduclaw env | grep -E "CLAUDE_CODE_OAUTH_TOKEN|ANTHROPIC_API_KEY"
# 2. Volume 有沒有掛對
docker compose exec duduclaw ls -la ~/.claude/
# 3. CLI 本身看得到什麼
docker compose exec duduclaw claude auth status

常見錯誤是忘了 docker compose up -d 在修改 .env重啟 container, env var 只在啟動時注入,熱改無效。

**第 3 步不能證明 token 還活著。**只要環境裡有 CLAUDE_CODE_OAUTH_TOKENclaude auth status 就會回報 loggedIn: true——它從來不檢查這個 token 是否還能實際認證。一顆已被撤銷或組織停用的 token,一樣會通過這個檢查。 要確認憑證是不是真的有效,看儀表板「帳號」頁該帳號卡片上的憑證狀態徽章 (未驗證/憑證損壞/token 無效/組織停用——健康帳號不顯示任何徽章), 或在 container 內直接跑一次真探測:

終端機視窗
docker compose exec duduclaw claude -p "reply ok" --model haiku --max-turns 1 --output-format json

看回傳 JSON 裡的 is_error / api_error_status 欄位。

Dashboard 打得到但 agent 回訊「請先執行 claude auth status

Section titled “Dashboard 打得到但 agent 回訊「請先執行 claude auth status」”

這是 v1.8.x 前版本的殘留訊息;v1.8.22+ 已改成依 FailureReason 分類的 zh-TW 訊息。若仍看到:

終端機視窗
docker compose exec duduclaw duduclaw --version
# 確認 1.8.22 以上;若非,拉最新 main + 重 build

症狀:透過 tailnet(*.ts.net)或反向代理網域開 dashboard,HTTP 頁面正常載入, 但即時資料一直轉圈圈;瀏覽器 DevTools 的 Network 面板可見 /ws 升級回 403

原因:WebSocket 的 Origin 白名單預設只含 loopback,你的對外網域不在其中。把它 加進白名單即可:

終端機視窗
# compose 的 environment: 或 .env
DUDUCLAW_ALLOWED_ORIGINS=duduclaw.your-tailnet.ts.net,duduclaw.yourdomain.com

或寫進 ~/.duduclaw/config.toml

[gateway]
allowed_origins = ["duduclaw.your-tailnet.ts.net"]

重啟後啟動 log 會印出生效的額外 origins。詳見 deployment-guide §5 WebSocket Origin 白名單

  • LINE / WhatsApp / Feishu 需要 HTTPS,確認 §10 已完成設定
  • 到 Dashboard → Channels 檢查該 channel 的連線狀態指示燈
  • 看 log:docker compose logs -f duduclaw | grep -i webhook

DuDuClaw 會透過 docker.sock 呼叫宿主機 Docker daemon 建立隔離容器 執行 agent tasks。若失敗:

終端機視窗
# 測試 socket 能否從容器內使用
docker compose exec duduclaw docker ps
# 要能看到宿主機上的 container 清單

若 Permission denied,多半是 SELinux / AppArmor 擋住。Linux 上可試:

volumes:
- /var/run/docker.sock:/var/run/docker.sock:rw
group_add:
- "${DOCKER_GID:-999}" # 對齊宿主機 docker group GID

確認 volume 確實存在:

終端機視窗
docker volume ls | grep duduclaw
# duduclaw_duduclaw-data
# duduclaw_duduclaw-claude
# duduclaw_duduclaw-codex
# duduclaw_duduclaw-gemini

若缺了某個,表示 compose 檔被改過或曾 docker compose down -v, 重新 claude auth login / codex login / gemini auth 即可。