Supabase CLI 與本機開發:用 Docker 在本機跑一整套 | Supabase 完整教學

2026/10/28
Supabase CLI 與本機開發:用 Docker 在本機跑一整套 | Supabase 完整教學

到目前為止,我們寫的每一行 SQL、每一個函式、每一條 RLS 政策,都是在雲端儀表板上敲出來的——這在學習階段很方便,但真要做產品就處處掣肘:改壞了沒有還原、多人協作互相覆蓋、更沒辦法離線開發。這一篇我們把戰場搬回你自己的電腦。**Supabase CLI(命令列工具)**讓你用 Docker 在本機一鍵拉起「一整套 Supabase」——資料庫、Auth、Storage、Realtime、Studio 全都在 localhost 上跑,離線、免費、想重置就重置。本篇帶你走完最核心的本機開發流程:安裝 CLI、supabase init 建專案、supabase start 啟動堆疊、supabase status 查連線、逛本機 Studio、supabase link 連遠端專案、讀懂 config.toml、跑 seed 種子資料,最後 supabase stop 收工。這也是 SB-5「工具與維運」段的第一篇。

前言

先一句話定義本篇主角:Supabase CLI 是官方提供的命令列工具,核心能力是「用 Docker 在你本機跑起一整套完整的 Supabase 服務堆疊」,讓所有開發與測試都能離線、在地進行,改壞了隨時重置,確認沒問題後再部署上雲。 它背後的設計哲學只有四個字——本機優先(Local-first):所有變更先在本機開發、測試,再推送到雲端,而不是拿線上環境當實驗場。

用一個類比理解「本機開發」為什麼重要。想像你在別人的正式廚房裡學做菜(雲端儀表板直接改線上專案):每一次試驗都用真食材、鍋子只有一組、失敗了收不回來,還可能撞到別的廚師。本機開發就像 Supabase 幫你在自己家裡蓋了一間一模一樣的練習廚房——同樣的爐具、同樣的食材(PostgreSQL、Auth、Storage 一應俱全),但隨你砸、隨你重來,練到滿意再把食譜(migrations)帶去正式廚房重現。這間「家裡的練習廚房」,就是 supabase start 用 Docker 幫你一鍵搭起來的東西。

而讓這一切成真的關鍵,是 Docker。Supabase 不是單一程式,而是十幾個服務組成的系統(資料庫、API Gateway、認證、儲存、即時訂閱、管理介面……)。CLI 的巧思在於:把這一整套打包成 Docker 容器,supabase start 一行指令就把它們全部拉起來,你不必手動安裝設定 PostgreSQL、Kong、GoTrue 這些元件。代價只有一個——你的電腦上得先有一個「正在執行」的容器環境。

本篇你會學到:

  • 安裝 CLI:brew/npx(專案相依)兩種主流方式,以及為什麼團隊常選 npx
  • 啟動本機堆疊:supabase init 建專案結構、supabase start 用 Docker 拉起全套服務、supabase status 查連線資訊
  • 本機 Studio 與 config.toml:在 localhost:54323 操作視覺化介面、讀懂本機環境的核心設定檔
  • 連遠端與 seed:supabase link --project-ref 綁定雲端專案、用 seed.sql 塞測試資料、supabase stop 正確收工

本篇聚焦「把本機環境跑起來」這一件事——migrations(schema 版控)與 branching(PR 預覽環境)是龐大主題,留到後續專篇細講。以下埠號、config.toml 欄位、預設帳密都以本文撰寫時的 CLI 版本為準,正式決策前請以官方文件為準。

核心概念

在敲任何指令之前,先建立兩張心智圖:一是「supabase start 到底在你電腦裡跑起了什麼」,二是「本機世界與雲端世界怎麼分工」。

一、本機 Docker 全套元件

當你執行 supabase start,CLI 會在背後用 Docker 同時拉起一組容器,各自扮演一個角色,湊成一套「和雲端幾乎等價」的 Supabase。核心服務與它們的預設埠如下:

服務預設埠角色說明
API Gateway(Kong)54321REST API、GraphQL、Storage 的「統一入口」,前端都打這個埠
PostgreSQL54322本機資料庫本體,預設帳密 postgres/postgres
Studio54323視覺化管理介面,等同雲端 Dashboard
Inbucket(郵件測試)54324攔截所有 Auth 認證信件,本機測試註冊/重設密碼不寄真信
Shadow Database54320供 db diff 比對用的影子資料庫(下一篇會用到)

一句話理解這張表的分工:前端/SDK 只認 54321(Kong 這個大門),大門背後才轉發給 Auth、Storage、PostgREST 等各服務;你要「用眼睛看資料」就開 54323(Studio);要「用 psql/連線字串直連資料庫」就用 54322。 而 Inbucket(54324)是本機開發的隱藏好朋友——測試「使用者註冊要收驗證信」的流程時,信不會真的寄出去,而是全被 Inbucket 攔下來,你打開它的網頁就能看到,完全不必準備真信箱。

首次 supabase start 時,CLI 需要下載這些服務的 Docker 映像(Image),依網速可能花幾分鐘;之後有快取就快了。啟動完成後,終端機會印出一整份連線資訊(API URL、DB URL、Studio URL、anon key、service_role key 等),這份資訊就是你接下來開發要用的一切。

二、本機世界 vs 雲端世界

第二張心智圖,也是新手最常搞混的地方:本機開發環境和你的雲端專案,是兩個獨立的世界。

┌─────────────── 本機世界(你的電腦)───────────────┐
│  supabase start   → Docker 拉起全套服務            │
│  localhost:54321  → API      localhost:54322 → DB │
│  localhost:54323  → Studio(本機視覺化介面)       │
│  資料隨你砸、隨你 supabase stop --no-backup 清空   │
└───────────────────────────────────────────────────┘
                      │
                      │  supabase link --project-ref <ref>
                      │  (只是「牽一條線」,不同步資料)
                      ▼
┌─────────────── 雲端世界(supabase.com)───────────┐
│  你的正式專案:真實使用者、正式資料                 │
│  未來用 db push / db pull 在兩邊之間流動 schema    │
│  (那是下一篇 migrations 的主題)                  │
└───────────────────────────────────────────────────┘

拆解這張圖的關鍵觀念:

  • 本機世界是你的沙盒。supabase start 拉起的一切都在 localhost,跟網路無關、跟你的雲端專案無關,你在這裡怎麼亂搞都不會影響線上任何一筆真實資料。
  • supabase link 只是「牽線」,不是「搬資料」。 它把本機的 supabase/ 資料夾綁定到某個雲端專案,好讓未來的部署指令(db push/db pull/gen types --linked)知道「目標是誰」。link 完之後,你的本機資料不會自動跑上雲端,雲端資料也不會自動下來。
  • 真正的資料/schema 流動要靠後續的 db push(本機推上去)和 db pull(雲端拉下來)——這是下一篇 migrations 的核心。本篇你只要先把「兩個世界+一條 link」的關係圖記牢。

三、關鍵術語速查

術語白話解釋
Supabase CLI官方命令列工具,用來在本機跑 Supabase、管理 migrations、連結雲端專案
容器執行環境(Container Runtime)Docker Desktop/OrbStack/colima/Podman 等,supabase start 的前置需求
supabase/ 目錄supabase init 建立的專案資料夾,放 config.toml、migrations、seed,應納入 git
config.toml本機環境的核心設定檔,控制各服務的埠、Auth、Storage 等行為
本機優先(Local-first)先在本機開發測試、再部署上雲的工作哲學
project-ref(專案參考碼)雲端專案的唯一識別碼,從 Dashboard 網址取得,supabase link 要用
seed(種子資料)seed.sql 裡的初始測試資料,每次 db reset 自動填入

實作範例

下面走一遍完整的本機開發起手式:安裝 CLI → init 建專案 → start 啟動 → status 查連線 → 逛本機 Studio → 調 config.toml → 寫 seed → link 遠端 → stop 收工。每一步都是可以直接敲的指令。

一、安裝 Supabase CLI

有兩種主流裝法。第一種是 macOS 用 Homebrew 全域安裝,適合把 CLI 當成一支全域工具:

# macOS:用 Homebrew 安裝到全域
brew install supabase/tap/supabase

# 之後升級
brew upgrade supabase

第二種、也是團隊協作更推薦的做法,是安裝為專案的開發相依套件,讓每個成員的 CLI 版本都由 package.json 鎖定,不會你用 2.1、我用 2.9 而行為不一致:

# 安裝為開發相依(推薦團隊統一版本)
npm install supabase --save-dev
# 或 pnpm add -D supabase / yarn add -D supabase / bun add -D supabase

用這種方式安裝後,所有指令都改用 npx 前綴呼叫(後文為簡潔起見都寫 supabase,若你是專案相依安裝,請自行在前面加 npx):

# 專案相依安裝:用 npx 呼叫
npx supabase --version

不論哪種方式,裝完先驗證一下:

# 確認安裝成功,會印出版本號(例如 2.x.x)
supabase --version

二、初始化專案:supabase init

進到你的應用程式根目錄,執行 init 建立 Supabase 的專案結構:

# 在專案根目錄執行,建立 supabase/ 資料夾與 config.toml
supabase init

它會產生一個 supabase/ 目錄,這就是往後所有本機設定與版控的家:

your-project/
└── supabase/
    ├── config.toml      # 本機環境的核心設定檔
    ├── seed.sql         # 種子資料(可選)
    ├── migrations/      # 遷移檔案目錄(下一篇的主角)
    └── functions/       # Edge Functions 目錄

這個 supabase/ 目錄應該整個納入 git(除了裡面的 .env 與 .temp/)——因為 config.toml、migrations、seed 都是「團隊要共享、要版控」的資產。

三、啟動本機堆疊:supabase start

重頭戲來了。先確認你的 Docker Desktop/OrbStack 正在執行(這是最常被忘記的一步),然後:

# 用 Docker 一鍵拉起整套 Supabase(首次會下載映像,需幾分鐘)
supabase start

啟動完成後,終端機會印出一整份連線資訊,長這樣(金鑰已截短):

Started supabase local development setup.

         API URL: http://127.0.0.1:54321
          DB URL: postgresql://postgres:postgres@127.0.0.1:54322/postgres
      Studio URL: http://127.0.0.1:54323
    Inbucket URL: http://127.0.0.1:54324
        anon key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
service_role key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

這份資訊就是你本機開發的「鑰匙圈」:前端把 API URL 當作 SUPABASE_URL、anon key 當作公開金鑰;需要用 SQL 工具直連資料庫時用 DB URL;service_role key 是伺服器端專用的超級金鑰,絕對不能外洩到前端。

小提醒:這些本機金鑰是所有本機環境共用的固定值(不是機密),可以放心寫在 .env.local 供本機開發用;但雲端專案的 service_role key 是真正的機密,兩者別搞混。

四、查看服務狀態:supabase status

如果終端機被清掉、忘了連線資訊,隨時可以用 status 把這份鑰匙圈再印一次:

# 查看目前本機服務狀態與所有連線資訊
supabase status

它會再列出 API URL、DB URL、Studio URL、各把金鑰等。想確認「本機到底有沒有在跑」、或要複製 anon key 貼到前端 .env 時,這個指令最常用。

五、逛本機 Studio

打開瀏覽器,前往 http://127.0.0.1:54323,你會看到一個和雲端 Dashboard 幾乎一模一樣的介面——這就是本機 Studio。在這裡你可以:

  • 用 Table Editor 建立、瀏覽、編輯資料表
  • 在 SQL Editor 執行任意 SQL 查詢
  • 管理 Auth 使用者、檢視 Storage Bucket
  • 測試查詢、觀察資料

它的最大價值是:你在雲端 Dashboard 學會的所有操作,在本機 Studio 原封不動就能用,但這裡動的是你本機那份「隨你砸」的資料庫,不會碰到任何線上資料。稍後(下一篇)你還會看到「在 Studio 改 schema → 用 db diff 自動生成 migration」的黃金工作流。

六、認識 config.toml

supabase/config.toml 是本機環境的「總控台」,控制每個服務的埠與行為。挑幾個最常改的區塊看:

# 專案識別碼,用來區分同一主機上的多個專案
project_id = "my-app"

[api]
enabled = true
port = 54321               # API Gateway(Kong)埠
schemas = ["public", "graphql_public"]  # 要暴露為 REST API 的 schema

[db]
port = 54322               # PostgreSQL 埠
shadow_port = 54320        # Shadow Database 埠(db diff 用)
major_version = 15         # 本機 PostgreSQL 主要版本

[studio]
enabled = true
port = 54323               # 本機 Studio 埠

[auth]
enabled = true
site_url = "http://127.0.0.1:3000"   # 前端網址,用於 Auth 重新導向
jwt_expiry = 3600                    # JWT Token 有效期(秒)

[storage]
enabled = true
file_size_limit = "50MiB"            # 單檔上傳大小上限

兩個實務要點:

其一,敏感值用 env() 語法引用,不要硬寫。 例如要設定 GitHub OAuth,把密鑰放進不納入 git 的 supabase/.env,再在 config.toml 這樣引用:

[auth.external.github]
enabled = true
client_id = "env(GITHUB_CLIENT_ID)"      # 從 supabase/.env 讀取
secret = "env(GITHUB_CLIENT_SECRET)"

其二——這是超高頻的坑——改完 config.toml 必須重啟才會生效:

# 修改 config.toml 後,要 stop 再 start 才會套用新設定
supabase stop && supabase start

七、準備 seed 種子資料

每次重置環境後都手動塞測試資料很煩,這就是 seed(種子資料) 的用武之地。在 supabase/seed.sql 寫下初始資料的 INSERT:

-- supabase/seed.sql:本機環境的初始測試資料

insert into public.categories (name, slug, description)
values
  ('電子產品', 'electronics', '手機、電腦、配件等'),
  ('服飾',     'clothing',    '男裝、女裝、童裝'),
  ('書籍',     'books',       '文學、技術、藝術')
on conflict (slug) do nothing;   -- 用 on conflict 讓 seed 可安全重複執行

seed 的填入時機是每次 supabase db reset(清空資料庫 → 重套 migrations → 執行 seed)。若你有多個 seed 檔想分開管理,可在 config.toml 指定執行順序:

[db.seed]
enabled = true
sql_paths = ["./seed.sql", "./seeds/products.sql"]   # 依序執行

db reset 的完整用法(連同 migrations)是下一篇的主題,本篇你先把「seed.sql 放在哪、什麼時候會被跑」記住即可。

本機練得差不多、想跟雲端專案建立關聯時,才需要 link。先登入:

# 互動式 OAuth 登入(會開瀏覽器);CI 環境則設 SUPABASE_ACCESS_TOKEN 環境變數
supabase login

# 看看你帳號下有哪些雲端專案,順便抄下 REFERENCE ID
supabase projects list

接著用 --project-ref 把本機綁定到指定的雲端專案。project-ref 就是 Dashboard 網址 https://supabase.com/dashboard/project/<這一段> 中的那一段:

# 把本機 supabase/ 綁定到指定雲端專案(會要求輸入資料庫密碼)
supabase link --project-ref abcdefghijklmnopqrst

再次強調:link 只是「牽線」——它讓 db push/db pull/gen types --linked 知道目標專案是誰,但不會自己搬動任何資料。要取消關聯就 supabase unlink。

九、收工:supabase stop

一天結束,把本機堆疊停掉、釋放記憶體與 CPU:

# 停止所有容器,但「保留資料」(下次 start 資料還在)——日常收工用這個
supabase stop

# 停止「並清除」所有本機資料(完整重置回全新)——環境搞亂時用這個
supabase stop --no-backup

到這裡,一趟最小可行的本機開發循環就完整了:start 開工 → 在 Studio/SQL 開發 → status 查資訊 → stop 收工,明天 start 接著做。

常見錯誤與最佳實踐

坑一:supabase start 直接報錯,其實是 Docker 沒開。 新手最常見的第一個卡關,就是興沖沖敲 supabase start,結果跳出「Cannot connect to the Docker daemon」之類的錯誤。原因幾乎都是——容器執行環境沒在跑。正確做法:start 之前,先確認 Docker Desktop/OrbStack/colima 已經啟動(macOS 可以看選單列的圖示,或用 docker info 確認能連上)。這是本篇第一鐵律:沒有正在執行的容器環境,本機堆疊一個容器都起不來。

坑二:埠號衝突(port already in use)。 54321~54324 這幾個埠若被別的程式(甚至另一個沒關乾淨的 Supabase 專案)佔用,start 會失敗。正確做法:先確認上一個專案有 supabase stop;或在 config.toml 裡改掉衝突的埠(記得改完 stop && start 重啟);真的卡住時 supabase stop --no-backup 清乾淨再重來。同一台機器要同時跑多個 Supabase 專案時,務必給每個專案不同的 project_id 與埠。

坑三:本機與遠端搞混,把測試操作打到正式環境。 最危險的坑——以為自己在本機亂試,其實指令打到了雲端正式專案。這通常發生在「已經 link 過、又沒看清楚指令目標」的時候。正確做法:牢記「本機世界(localhost、start/stop/本機 Studio)」和「雲端世界(db push/db pull/--linked)」是兩套指令;任何會碰雲端的操作(尤其 db push)執行前,先 supabase projects list 或 supabase status 確認「現在 link 的是不是我以為的那個專案」,別在生產專案上手滑。

坑四:忘了先 link,就想跟雲端互動。 還沒 supabase link(也沒 login)就直接下 db push、gen types --linked,CLI 會抱怨找不到關聯的專案。正確做法:與雲端相關的操作前,先確認流程是「supabase login →(supabase projects list 抄 ref)→ supabase link --project-ref <ref>」,link 成功後這些指令才有明確目標。反過來說,如果你只是在本機開發(start/stop/Studio/seed),根本不需要 link,別畫蛇添足。

坑五:改了 config.toml 卻沒重啟,然後以為設定壞了。 在 config.toml 調了埠、Auth site_url 或 Storage 上限,結果行為沒變、還以為是 bug。正確做法:config.toml 的變更需要 supabase stop && supabase start 才會套用——它不是熱重載。改完設定沒生效,第一個要檢查的就是「有沒有重啟」。

最佳實踐總結:

  • start 前先開 Docker:確認容器執行環境正在跑,這是所有本機開發的前置條件
  • 團隊用 npx 安裝:把 CLI 當專案開發相依,用 package.json 鎖版本,避免成員間行為不一致
  • supabase/ 納入 git,但排除 .env 與 .temp/:config.toml、migrations、seed 要共享版控;密鑰與暫存不進 git
  • 分清 stop 三態:stop 保留資料、stop --no-backup 清空重置、db reset 重套 schema 與 seed
  • 碰雲端前先確認 link 目標:db push 等指令執行前用 status/projects list 核對專案,別誤傷生產
  • 改 config.toml 記得重啟:stop && start 才會套用新設定
  • 細節以官方為準:埠號、config.toml 欄位、預設帳密都可能隨 CLI 版本調整

小結

這是 Supabase 系列教學的第 039 篇,也是 SB-5「工具與維運」段的開篇。上一篇《向量索引與自動 embeddings》我們替 RAG 的檢索加了速、替 embedding 建了零漂移的自動管線,把「運算與 AI」段收得漂漂亮亮——但也留下一個尷尬:到那篇為止,我們所有的 SQL、函式、索引都還是在雲端儀表板上手敲的,缺一套順手、可版控、可重現的本機開發流程。這一篇就補上了這塊拼圖。

核心觀念濃縮成一句話:Supabase CLI 讓你用 supabase start 在本機以 Docker 一鍵拉起「一整套 Supabase」(db/auth/storage/studio/realtime),在 localhost 上離線、免費、隨意重置地開發;本機世界(start/stop/本機 Studio)與雲端世界是兩個獨立的環境,supabase link --project-ref 只在兩者間「牽一條線」,不搬資料;改 config.toml 要 stop && start 重啟,收工用 supabase stop(保留)或 --no-backup(清空)。

  • 安裝與初始化:brew 全域或 npx(專案相依,團隊推薦)安裝;supabase init 建立 supabase/ 目錄
  • 啟動與查詢:supabase start(需先開 Docker)拉起全套服務;supabase status 隨時查連線資訊與金鑰
  • 本機 Studio:http://127.0.0.1:54323,等同雲端 Dashboard,但動的是你本機那份沙盒資料
  • 設定與資料:讀懂 config.toml(埠/Auth/Storage、env() 引用敏感值);用 seed.sql 準備測試資料
  • 連遠端與收工:supabase link --project-ref 綁定雲端專案(只牽線不搬資料);supabase stop 收工

本機環境搭好了,你已經有一間「隨你砸的練習廚房」。但練習的成果(那些資料表、函式、RLS 政策)該怎麼變成「可版控、可重現、能安全部署到雲端」的程式碼?答案就是 migrations(資料庫遷移)。下一篇《Migrations 資料庫遷移》,我們會把在本機 Studio 敲出來的每一次 schema 變更,都變成一支帶時間戳、納入 git、能一鍵重播的遷移檔——讓「本機開發 → 測試 → 生產」形成一條乾淨、可追溯、永不手滑改線上的單向流水線。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。

本週主打

AI 自動化入門包

你每天手動在做的那些煩事,其實 AI 可以自己跑。這份給你 10 個照著做就會的自動化工作流 + 50 個複製即用的提示詞,不用會寫程式。

看看這個產品 →