讓 AI 真的幫你做事:從零搭建 Dokploy + Cloudflare Tunnel 的 AI 協作全記錄

不教 prompt 技巧。直接看一次真實案例——我花一個下午,讓 AI 把公網可訪問的自架服務平台從零架起來,過程中踩了 3 個坑,AI 每次都自己爬出來。提煉 5 個「人類側」操作心法,附完整技術細節。

讓 AI 真的幫你做事:從零搭建 Dokploy + Cloudflare Tunnel 的 AI 協作全記錄

我不想教你 prompt engineering,那是三年前的事。今天給你看一個真實案例:

一個下午,我用 AI 把「公網可訪問的自架服務平台」從零架起來——Dokploy 面板 + Cloudflare Tunnel + Traefik wildcard 路由 + 把 Dokploy 面板本身也對外。過程踩了三個坑,AI 每次都自己爬出來。

本文目標:把這次過程中讓 AI 真正有效率做事的「人類側」操作提煉出來,附上完整技術細節,下次你也能這樣用。

最終戰果(先展示)

  • *.itsmygo.uk 任何子網域都自動指到家裡 Dokploy →加服務不用再碰 Cloudflare
  • https://dokploy.itsmygo.uk 可從任何地方登入面板(配 2FA +可加 Cloudflare Access)
  • Dokploy 上部署的服務公網 200 回應
  • 全程零開 port、家用路由器不用動、無公網 IP

為什麼這類任務最適合用 AI

這種任務的特徵:

  • 步驟多但不難:每一步有官方文件,但拼起來很累
  • 有選擇岔路:SSL 要 Flexible 還 Full?Tunnel 裝哪台?Swarm 還是單機?
  • 會踩坑但不致命:錯了回溯成本低
  • 重複性低:做完可能一年不碰第二次

AI 在這類場景殺傷力最大——它讀過所有文件、能判斷岔路、快速驗證,還有你沒有的耐心。你出腦,它出手。

但要 AI 真的能做事,不是丟一句「幫我架 Dokploy」就行。以下五件事少一件都不行。


心法 1|開局給「環境快照」,不是給「任務」

我的開頭 prompt 結構長這樣:

【我的環境】
- Dokploy 版本:v0.29.0,架在內網 http://192.168.50.217:3000
- 已新增第二台遠端伺服器:192.168.50.10(使用者 sk,SSH Key 已設定)
- 網域:itsmygo.uk,DNS 已託管在 Cloudflare
- 作業系統:Linux

【我想達成的目標】
1. 在 Cloudflare 建立一條 Tunnel,指向 Dokploy 機器上的 Traefik...
(略)
5. Dokploy 裡的服務 SSL 走 HTTP 即可(由 Cloudflare 處理 TLS)
Code language: JavaScript (javascript)

三種資訊一定要齊:

  1. 你手上有什麼(機器、網域、已裝的東西、帳號狀態)
  2. 你想要什麼(白話列清楚,編號)
  3. 你的偏好與限制(例:SSL 走 HTTP、不想動路由器、不想裝額外工具)

為什麼這重要

AI 不會 ping 你家路由器、不會猜你的網域。你沒講,AI 就得問(浪費往返);你講錯,AI 照錯的做。

特別記得講「限制」。我這次說「SSL 走 HTTP 即可」一句話,AI 就自動選了 Flexible 模式,沒建議我搞 Full + origin cert,直接省掉一整個分支。


心法 2|授權邊界講明白:「除非要登入才通知我」

第二輪我補了這句:

直接幫我全部完成 除非有要我登入的地方通知我

這句話做了兩件事:

  • 授權自主行動:AI 不用每一步問「要繼續嗎」
  • 但劃出紅線:碰到只有我能做的事才停下來(例:登入 Cloudflare 後台建 API token、登入 Dokploy 後台建 API key)

AI 立刻列出「我需要你做的唯一一件事」,清楚告訴我:去哪個網址、點哪個按鈕、要勾哪些權限。其他部分它包了。

對比失敗做法

如果你只說「幫我架」,AI 會謹慎,每一步都問,反覆確認,體驗極差。 如果你說「什麼都不用問,直接做」,AI 會卡在需要 credential 的地方硬試,浪費時間。

折衷這句「除非要登入才通知我」最好用


心法 3|讓 AI 先看現場再動手,不是反過來

拿到 prompt 後,AI 第一件事不是裝 cloudflared,是:

ip -4 addr show
docker ps
curl localhost:3000
Code language: CSS (css)

它發現了一件驚人的事——Claude Code 跑在 Dokploy 主機本身(skroom 這台就是 192.168.50.217)。

意思是:原本預期要 SSH 到 .217 安裝 cloudflared,根本不需要!local 直接執行就好。

Primary working directory: /home/sk/work
機器 IP:192.168.50.217
hostname:skroom
→ 這台就是 Dokploy 主機
Code language: JavaScript (javascript)

省下至少 10 分鐘的 SSH key 配置 + ssh-copy-id + known_hosts + sudoer 確認

對應人類側操作

不要在 prompt 裡預設 AI 對環境的認知。讓 AI 先自己看一眼。現代 AI 工具(Claude Code、Codex CLI、cursor agent 等)都能執行 shell 指令,幾個 ls / docker ps / cat 就比你口頭描述清楚一百倍。


心法 4|遇到錯誤讓 AI 自己診斷

這次踩了三個坑,每個都是 AI 自己診斷 + 修好。

踩坑 1:Cloudflare API Token 被 IP Filter 擋

AI 建 token 後第一個 API call 回:

{"code": 9109, "message": "Cannot use the access token from location: 2001:b011:...:381b"}
Code language: JSON / JSON with Comments (json)

AI 沒硬試別的 endpoint。它識別出是Client IP Filtering 在擋——我建 token 時不小心勾了 IP 限制。它告訴我怎麼改,一條路走到底。

踩坑 2:Better Auth 的 Invalid origin + 30 分鐘快取

Dokploy 面板對外 dokploy.itsmygo.uk 可以打開,但登入時跳 Invalid origin

AI 的診斷流程:

  1. Dokploy 用 Better Auth → 看它的 trustedOrigins 設定
  2. 掃 container env 沒有相關變數 → 一定在 DB
  3. \d user 發現有 trustedOrigins 欄位,UPDATE 加上 https://dokploy.itsmygo.uk
  4. 改完沒效!→ 在 bundle 裡 grep,發現 UN=30*6e4(30 分鐘)有快取
  5. 重啟 Dokploy 容器,讓快取清空

五步內定位 + 修好。要是我自己做,光搜「Dokploy Invalid origin」就得半小時。

踩坑 3:docker restart 搞壞 Swarm DNS

這是最騷的一個。AI 用 docker restart dokploy.1.xxx 重啟 Dokploy,結果 Traefik 開始回 502。

AI 的自我修正:

Traefik → dokploy 的 DNS:
dokploy-traefik: `getent hosts dokploy` → NXDOMAIN
Code language: JavaScript (javascript)

發現問題:Dokploy 是 Docker Swarm 的 service,用 docker restart 重啟個別容器會讓 Swarm overlay DNS 更新失敗。

正確做法:docker service update --force dokploy,走 Swarm 機制重啟。

改完 30 秒內恢復。AI 主動把這個踩坑講清楚,下次就不會再犯:

記住一件事:**以後 Dokploy 的容器要重啟,永遠用 docker service update --force <service>,不要 docker restart <container>**。

對應人類側操作

讓錯誤留在對話裡,不要跳過。很多人看到 AI 出錯就手動介入或重啟對話,等於浪費了 AI 最有價值的能力——在錯誤中學習並修正

遇到 AI 做錯,給它:

  • 完整的錯誤訊息
  • 「自己查為什麼」的空間
  • 「改完說明怎麼回事」的要求

它會主動 grep 程式碼、查 log、試多種假設。這種自我糾錯是現代 agent 架構的核心能力。


心法 5|追問原理與取捨,不只拿結果

做到一半我問:

所以這個把 3000 port 用掉了嗎

這題的表層答案是「沒有」。但 AI 給的回應包含:

  • 實際 ss -tlnp 驗證 host port
  • Docker 層、Swarm 層、容器內三層 port 的差別
  • Dokploy 表單三個 port 欄位各自意義
  • 為什麼 Domain 分頁的 Container Port 才是 Traefik 路由的依據

這個知識不是我從官方文件找的,是我「帶著疑問問 AI」挖出來的

後面還問了:

  • 「那這兩個服務的 port 如何對應到 dokploy」→ 拿到 Traefik runtime config 對照表
  • 「如果我要在部署一個 whoami3 到 .10 可以嗎」→ 拿到多節點架構的取捨分析
  • 「那是不是 .10 那台都裝後端服務 就不會有問題了」→ 確認正確架構

對應人類側操作

每當 AI 給你一個「可以」的答案,追一句「為什麼/還有什麼選項/什麼時候不該這樣」

這樣做會得到:

  • 該架構的適用邊界
  • 其他替代方案(省得以後後悔)
  • 踩坑預警(某個狀況會失敗)

光拿結果等於請了個外包工人。追問原理等於請了個顧問。差別在一句話。


Part 2|完整技術內容(供踩到相同題目的人 copy-paste)

把上面過程中完成的所有技術細節整理出來。

2.1 Cloudflare Tunnel 建立(懶人版)

DNS 策略:wildcard CNAME

類型: CNAME
名稱: *
目標: <tunnel-uuid>.cfargotunnel.com
Proxied: 開(橘色雲)
Code language: HTTP (http)

為什麼用 wildcard:之後在 Dokploy 加任何子網域(vault、whoami、blog…)都自動生效,完全不用回 Cloudflare 加 DNS。

Cloudflare SSL 模式選 Flexible

  • 瀏覽器 ↔ Cloudflare:HTTPS(CF 幫你處理 TLS)
  • Cloudflare ↔ 你家 Traefik:HTTP(透過 tunnel,自帶加密)

重定向迴圈防止:Always Use HTTPS 打開(讓 http:// 的請求自動 301 到 https://)。

Tunnel Ingress 設定

{
  "ingress": [
    {
      "hostname": "*.itsmygo.uk",
      "service": "http://localhost:80",
      "originRequest": {
        "noTLSVerify": true,
        "connectTimeout": 30
      }
    },
    { "service": "http_status:404" }
  ]
}
Code language: JSON / JSON with Comments (json)

注意:

  • service: http://localhost:80 → cloudflared 跟 Traefik 在同一台機器
  • HTTP Host Header 保持空白(預設值就是空白)→ 原始的 xxx.itsmygo.uk 會傳到 Traefik,Traefik 才能路由

API 權限設定(建 Token 時)

  • Account → Cloudflare Tunnel → Edit
  • Zone → DNS → Edit
  • Zone → Zone Settings → Edit
  • Zone Resources:Include → Specific zone → 你的網域
  • Client IP Filtering 留空(不然 AI 這邊的 IP 可能被擋,如我踩的第一個坑)

2.2 Traefik 三種 port,你只需要動一個

Dokploy 新手最常混淆的地方。

Port 位置 例子欄位 用途
主機 published port Advanced → Ports 分頁 直接對主機 0.0.0.0 開(docker run -p)。走 Traefik 就不要填
容器內部 port 容器 Dockerfile 的 EXPOSE Image 本身監聽的 port。whoami=80、node app 慣用 3000、golang 慣用 8080
Traefik routing port Domains → Container Port Traefik 要打到容器內部哪個 port。這個才是你日常會動的欄位

實際看 Traefik 在做什麼:

docker exec dokploy-traefik wget -qO- http://localhost:8080/api/http/services
# 會看到:
# app-xxx-service → http://app-xxx:80
#                   ↑ swarm service name   ↑ Domain.ContainerPort
Code language: PHP (php)

2.3 多節點架構:別讓後端服務跟 tunnel 打架

Dokploy 的 remote server 不是加入同一個 Swarm 當 worker,是獨立 Docker 主機。代表:

  • .217 的 Traefik 不知道 .10 上的容器
  • Wildcard tunnel 只能落到一台

正解(給起步 / 副業 / 家用)

機器 裝什麼 要不要 tunnel
.217(有 tunnel) 有公開 URL 的東西(前端、給瀏覽器打的 API)
.10(無 tunnel) 後端服務(DB、Redis、Queue、定時 job)

跨機通訊:LAN IP + published port (host mode)

例:Postgres 在 .10,API 在 .217:

  1. Dokploy 部署 Postgres 到 .10
  2. Ports 分頁加:5432:5432 tcp,Publish Mode 選 host(不是 ingress)
  3. .217 的 API 容器 env:DATABASE_URL=postgresql://user:[email protected]:5432/db

注意:published port 等於 DB 開在內網 LAN 上,家用路由器別把 5432 打洞,DB 密碼要夠強。

2.4 讓 Dokploy 面板自己對外(踩坑密集區)

步驟 1:Traefik dynamic config 加 router

# /etc/dokploy/traefik/dynamic/dokploy-public.yml
http:
  routers:
    dokploy-public-router:
      rule: Host(`dokploy.itsmygo.uk`)
      service: dokploy-service-app
      entryPoints:
        - web
Code language: PHP (php)

Traefik 自動熱載,不用重啟。

步驟 2:登入會跳 Invalid origin —— Better Auth 白名單

-- 連進 Dokploy 的 postgres container
UPDATE "user"
SET "trustedOrigins" = array_append(
  COALESCE("trustedOrigins", ARRAY[]::text[]),
  'https://dokploy.itsmygo.uk'
)
WHERE NOT ('https://dokploy.itsmygo.uk' = ANY(COALESCE("trustedOrigins", ARRAY[]::text[])));
Code language: PHP (php)

步驟 3:這欄位有 30 分鐘快取,一定要重啟 Dokploy

且一定要用 Swarm 的方式重啟:

# ✅ 正確
docker service update --force dokploy

# ❌ 錯誤:這會搞壞 overlay 網路的 DNS
docker restart dokploy.1.xxxxx
Code language: CSS (css)

步驟 4:安全三層疊(強烈建議)

層級 保護範圍 設定位置
Dokploy 2FA (TOTP) 密碼外洩時擋帳號接管 Dokploy Profile → Security
Cloudflare Access + Google SSO 0-day 防護(Dokploy 登入頁都看不到) Zero Trust → Access → Applications
Policy allow-list 只有特定 email 能通過 Access Policy

Cloudflare Access ≤50 人免費,10 分鐘設定。個人站強烈建議做


結語|什麼任務適合這樣丟給 AI?什麼不適合?

適合(這次屬於這類)

  • 步驟多、單步不難、有官方文件:架設、部署、整合、遷移類任務
  • 可以在沙盒驗證:錯了能 rollback、影響範圍小
  • 需要讀多個文件並權衡:不同家工具、不同版本、多種配置

不適合

  • 強烈依賴人類判斷的商業決策:該不該做、定價、策略
  • 影響無法回溯的操作:刪 production DB、送出 email 給用戶、正式環境改設定
  • 你自己還沒想清楚要什麼的東西:AI 會幫你做出「一個」解法,但可能不是你要的那個

五條心法回顧

  1. 開局給環境快照,不是給任務(現況 + 目標 + 限制 三件齊全)
  2. 授權邊界講明白(「除非要登入才通知我」這句話很神)
  3. 讓 AI 先看現場再動手(它 ls 比你描述準)
  4. 遇到錯誤讓 AI 自己診斷(別手動介入,它自我修正能力比你想像的強)
  5. 追問原理與取捨(光拿結果=外包工,追問=顧問)

做對這五件事,下次你 2 小時能做完的事,AI 幫你半小時;2 週沒把握的事,AI 陪你把它壓到 2 小時。

真的不是 prompt 玄學,是把人類側的準備工作做到位

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *