# Supabase CLIの使い方

Supabase CLIを使ってローカル環境で開発する際のメモ。インターネット接続なしで開発でき、データベースの変更を安全にテストできる。

# インストール

# macOS/Linux

# Homebrewを使用(推奨)
brew install supabase/tap/supabase

# npmを使用
npm install -g supabase

# または、npxで直接実行
npx supabase --version

# Windows

# Scoopを使用
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase

# npmを使用
npm install -g supabase

# Dockerのインストール

Supabase CLIはDockerを使用するため、Docker Desktopが必要。

インストール後、Dockerが起動していることを確認:

docker --version
docker ps

# プロジェクトの初期化

supabase init

# 以下のディレクトリ構造が作成される:
# supabase/
#   ├── config.toml          # Supabase設定ファイル
#   ├── migrations/          # データベースマイグレーションファイル
#   ├── seed.sql            # シードデータ(オプション)
#   └── functions/          # エッジ関数(オプション)

# ローカル環境の起動と停止

# 起動

supabase start

# 起動後、以下の情報が表示される:
# API URL: http://localhost:54321
# GraphQL URL: http://localhost:54321/graphql/v1
# DB URL: postgresql://postgres:postgres@localhost:54322/postgres
# Studio URL: http://localhost:54323
# Inbucket URL: http://localhost:54324
# JWT secret: your-jwt-secret
# anon key: your-anon-key
# service_role key: your-service-role-key

初回起動

初回起動時は、Dockerイメージのダウンロードとコンテナの起動に数分かかる。2回目以降は数秒で起動する。

# ステータスの確認

supabase status

# 停止

supabase stop

# 再起動

supabase start
# データは保持されたまま再起動される

# 完全削除

# ローカル環境を完全に削除(データも含む)
supabase stop --no-backup

# または、Dockerコンテナを直接削除
docker stop supabase_db_local
docker rm supabase_db_local

# ローカル環境の設定

# 環境変数の設定

supabase startで表示されたURLとキーを環境変数に設定。

# .env.local
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-local-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-local-service-role-key

# Supabase Studio(ローカル)

ローカル環境のSupabase Studioにアクセス:

http://localhost:54323

ローカルのSupabase Studioでは、テーブルの作成・編集、SQLエディタでのクエリ実行、認証ユーザーの管理などが可能。

# データベースマイグレーション

# マイグレーションファイルの作成

supabase migration new create_posts_table

# supabase/migrations/YYYYMMDDHHMMSS_create_posts_table.sql が作成される

命名規則:

supabase migration new create_posts_table
supabase migration new add_user_email_index
supabase migration new update_posts_rls_policy
supabase migration new drop_old_columns

# マイグレーションファイルの編集

-- supabase/migrations/YYYYMMDDHHMMSS_create_posts_table.sql
CREATE TABLE posts (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  title TEXT NOT NULL,
  content TEXT,
  user_id UUID REFERENCES auth.users(id),
  created_at TIMESTAMP WITH TIME ZONE DEFAULT TIMEZONE('utc'::text, NOW()) NOT NULL
);

ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

CREATE POLICY "誰でも読み取り可能" ON posts
  FOR SELECT USING (true);

CREATE POLICY "認証済みユーザーのみ書き込み可能" ON posts
  FOR INSERT WITH CHECK (auth.role() = 'authenticated');

# マイグレーションの適用

# データベースをリセットしてマイグレーションを適用
supabase db reset

# または、新しいマイグレーションのみ適用
supabase migration up

データのリセット

supabase db resetは、データベースを完全にリセットし、すべてのマイグレーションを再適用する。ローカルのデータはすべて削除される。

# マイグレーションの状態確認

supabase migration list

# 出力例:
# 20240101000000_create_posts_table (applied)
# 20240102000000_add_user_email_index (applied)
# 20240103000000_update_posts_rls_policy (pending)

# マイグレーションのロールバック

# 最後に適用したマイグレーションをロールバック
supabase migration down

# 特定のマイグレーションまでロールバック
supabase migration down --target 20240101000000

# リモートプロジェクトとの連携

# リモートプロジェクトとのリンク

supabase link --project-ref your-project-ref

# プロジェクト参照IDは、SupabaseダッシュボードのURLから取得
# https://app.supabase.com/project/your-project-ref

リンク後、supabase/config.tomlにプロジェクトIDが保存される。

# リモートへのマイグレーションのプッシュ

supabase db push

本番環境への適用

supabase db pushは本番環境にも影響する可能性がある。本番環境に適用する前に、必ずステージング環境でテストする。

# リモートからのマイグレーションのプル

supabase db pull

# リモートからのスキーマの差分取得

# リモートとローカルのスキーマの差分を確認
supabase db diff

# 差分をマイグレーションファイルとして生成
supabase db diff -f migration_name

# 型定義の生成

# ローカル環境から型定義を生成

supabase gen types typescript --local > types/supabase.ts

# リモートプロジェクトから型定義を生成

supabase gen types typescript --project-id your-project-id > types/supabase.ts

# または、リンク済みのプロジェクトから生成
supabase gen types typescript --linked > types/supabase.ts

# 生成された型定義の使用例

import { Database } from './types/supabase'
import { createClient } from '@supabase/supabase-js'

const supabase = createClient<Database>(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

// 型安全なクエリ
const { data } = await supabase
  .from('posts')
  .select('*')

# シードデータの投入

# seed.sqlの作成

-- supabase/seed.sql
INSERT INTO posts (title, content, user_id)
VALUES
  ('最初の投稿', 'これはテスト投稿です', '00000000-0000-0000-0000-000000000000'),
  ('2番目の投稿', 'これもテスト投稿です', '00000000-0000-0000-0000-000000000000');

# シードデータの投入

# シードデータを投入
supabase db reset

# db resetは、マイグレーションの適用後に自動的にseed.sqlを実行する

# シードデータの手動実行

# シードデータのみ実行(マイグレーションは適用しない)
supabase db seed

# よく使うCLIコマンド一覧

# プロジェクト管理
supabase init
supabase status
supabase logs

# ローカル環境の管理
supabase start
supabase stop

# データベース操作
supabase db reset
supabase migration new migration_name
supabase migration up
supabase migration down
supabase migration list
supabase db seed

# リモートとの連携
supabase link --project-ref your-project-ref
supabase db push
supabase db pull
supabase db diff

# 型定義の生成
supabase gen types typescript --local > types/supabase.ts
supabase gen types typescript --project-id your-project-id > types/supabase.ts
supabase gen types typescript --linked > types/supabase.ts

# ローカル開発のワークフロー

  1. プロジェクトの初期化

    supabase init
    
  2. ローカル環境の起動

    supabase start
    
  3. マイグレーションファイルの作成

    supabase migration new create_posts_table
    
  4. マイグレーションファイルの編集

    • supabase/migrations/ディレクトリ内のSQLファイルを編集
  5. マイグレーションの適用

    supabase db reset
    
  6. 型定義の生成

    supabase gen types typescript --local > types/supabase.ts
    
  7. 開発とテスト

    • ローカル環境でアプリケーションを開発・テスト
  8. リモートへの反映(準備ができたら)

    supabase link --project-ref your-project-ref
    supabase db push
    

# 実装時の注意点

# マイグレーションファイルの命名規則

明確で説明的な名前を付ける。

# 良い例
supabase migration new create_posts_table
supabase migration new add_user_email_index

# 悪い例
supabase migration new migration1
supabase migration new update

# マイグレーションファイルの管理

マイグレーションファイルは必ずGitで管理する。

# .gitignoreに追加しない
# supabase/migrations/ は必ずコミットする

# マイグレーションの順序

マイグレーションは時系列順に適用されるため、依存関係を考慮する。

# 1. テーブル作成
supabase migration new create_posts_table

# 2. インデックス追加
supabase migration new add_posts_indexes

# 3. RLSポリシー追加
supabase migration new add_posts_rls_policies

# 型定義の自動生成

スキーマ変更後は、必ず型定義を再生成する。

supabase db reset
supabase gen types typescript --local > types/supabase.ts

# 環境変数の管理

開発環境と本番環境で異なる環境変数を使用する。

# 開発環境の設定
# .env.local
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-local-anon-key

# 本番環境の設定
# .env.production
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-production-anon-key

# よくあるエラーと対処法

# ローカル環境が起動しない

エラー: Error: failed to start: Docker is not running

原因: Docker Desktopが起動していない、またはDockerがインストールされていない

対処:

  • Docker Desktopを起動
  • Dockerがインストールされているか確認: docker --version
  • Docker Desktopの設定で、リソースが十分に割り当てられているか確認

# ポートが既に使用されている

エラー: Error: port 54321 is already in use

原因: 既にSupabaseのローカル環境が起動している、または他のアプリケーションがポートを使用している

対処:

# 既存のSupabase環境を停止
supabase stop

# または、使用中のポートを確認
lsof -i :54321

# プロセスを終了
kill -9 <PID>

# マイグレーションが適用されない

原因: マイグレーションファイルに構文エラーがある、またはマイグレーションの順序が正しくない

対処:

# マイグレーションの状態を確認
supabase migration list

# データベースをリセットして再適用
supabase db reset

# マイグレーションファイルの構文を確認
# SQLエディタで実行してエラーを確認

# ローカル環境とリモート環境の不一致

原因: ローカルとリモートで異なるマイグレーションが適用されている

対処:

# リモートのマイグレーションをローカルに取得
supabase db pull

# または、ローカルのマイグレーションをリモートに適用
supabase link --project-ref your-project-ref
supabase db push

データの同期

supabase db pushはリモートのデータベースを変更する。本番環境に適用する前に、必ずバックアップを取得し、ステージング環境でテストする。

# 型定義が更新されない

原因: スキーマ変更後に型定義を再生成していない

対処:

# マイグレーションを適用後、型定義を再生成
supabase db reset
supabase gen types typescript --local > types/supabase.ts

# Dockerコンテナが起動しない

原因: Dockerのリソース不足、またはイメージの破損

対処:

# Dockerのリソースを確認
docker system df

# 不要なイメージやコンテナを削除
docker system prune -a

# Supabaseのイメージを再ダウンロード
supabase stop
supabase start

# 参考リンク

同じタグを持つ記事をピックアップしました。