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) | 54321 | REST API、GraphQL、Storage 的「統一入口」,前端都打這個埠 |
| PostgreSQL | 54322 | 本機資料庫本體,預設帳密 postgres/postgres |
| Studio | 54323 | 視覺化管理介面,等同雲端 Dashboard |
| Inbucket(郵件測試) | 54324 | 攔截所有 Auth 認證信件,本機測試註冊/重設密碼不寄真信 |
| Shadow Database | 54320 | 供 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 放在哪、什麼時候會被跑」記住即可。
八、連結遠端專案:supabase link
本機練得差不多、想跟雲端專案建立關聯時,才需要 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、能一鍵重播的遷移檔——讓「本機開發 → 測試 → 生產」形成一條乾淨、可追溯、永不手滑改線上的單向流水線。