Supabase CLI を活用した環境管理ガイド


# Supabase CLI を活用した環境管理ガイド：開発・ステージング・本番を徹底解説

現代のWeb開発において、効率的かつ安全な環境管理はプロジェクトの成功に欠かせません。  
特に、Next.jsとSupabaseを組み合わせて使用する場合、開発環境（Development）、ステージング環境（Staging）、本番環境（Production）を適切に分けて管理することが重要です。

本記事では、Supabase CLIを活用し、Next.jsプロジェクトを前提に、複数環境の設定・管理方法を専門家の視点から詳細に解説します。

実践的なサンプルコードとともに、ステップバイステップで進めていきますので、ぜひ参考にしてください。

## 前提条件

この記事を進める前に、以下の環境が整っていることを確認してください。

- **Node.js**: 最新の安定版（推奨: v18以上）
- **npm または yarn**: パッケージマネージャ
- **Next.jsプロジェクト**: `npx create-next-app@latest`を使用して作成されたプロジェクト
- **Supabaseアカウント**: [Supabase公式サイト](https://supabase.com/)で無料アカウントを作成
- **GitHubリポジトリ**: プロジェクトを管理するためのリポジトリ（オプションだが推奨）

---

## Supabase CLIの導入と基本設定

Supabase CLIは、Supabaseプロジェクトの管理や運用を効率化するための強力なツールです。以下の手順でSupabase CLIを導入し、基本的な設定を行います。

### Supabase CLIのインストール

Supabase CLIは複数の方法でインストールできます。以下の方法から自分に合ったものを選択してください。

#### Homebrew（macOS/Linux）

Homebrewを利用している場合、以下のコマンドで簡単にインストールできます。

```bash
brew install supabase/tap/supabase
```

#### npm（Node.jsを利用している場合）

npmを利用してグローバルにインストールします。

```bash
npm install supabase -g
```

#### ダウンロード（公式リリースから）

1. [Supabase CLIのGitHubリリースページ](https://github.com/supabase/cli/releases)にアクセスします。
2. 使用しているOSに対応するバイナリをダウンロードします。
3. ダウンロードしたバイナリを実行可能なパスに配置します。

**注意点**:
- インストール後、以下のコマンドでインストールが成功したか確認します。

  ```bash
  supabase --version
  ```

### プロジェクトの初期化

Supabase CLIをインストールしたら、次にプロジェクトを初期化します。プロジェクトディレクトリ内で以下のコマンドを実行します。

```bash
supabase init
```

このコマンドにより、以下のディレクトリ構造が作成されます。

```plaintext
your-project/
├── supabase/
│   ├── config.toml
│   ├── migrations/
│   ├── functions/
│   └── .env
├── src/
├── package.json
└── その他のプロジェクトファイル
```

**プロジェクトディレクトリの説明**:

- `supabase/`: Supabaseに関連する設定やリソースを管理するディレクトリ。
- `migrations/`: データベースマイグレーションファイルを管理。
- `functions/`: Supabase Functions（サーバーレス関数）を管理。
- `.env`: 環境変数を定義するファイル。
- `src/`: Next.jsアプリケーションのソースコード。
- `package.json`: Node.jsプロジェクトの依存関係やスクリプトを管理。

---

## プロジェクトディレクトリ構造の詳細

Supabase CLIによって作成されたプロジェクトディレクトリの詳細を解説します。各ディレクトリ・ファイルの役割と活用方法を理解することで、プロジェクト管理がより効率的になります。

### `supabase/`ディレクトリの解説

`supabase/`ディレクトリは、Supabaseに関連するすべての設定やリソースを管理する中心的な場所です。このディレクトリ内には、設定ファイル、マイグレーションファイル、サーバーレス関数などが含まれます。

#### 1. `config.toml`

- **役割**: Supabase CLIの設定ファイル。プロジェクトリファレンスやデータベース接続情報、関数ディレクトリの設定などが含まれます。
- **サンプルコード**:

  ```toml
  # supabase/config.toml

  project_ref = "your-project-ref"

  [database]
  url = "postgres://user:password@localhost:5432/mydb"

  [functions]
  directory = "supabase/functions"
  ```

  **詳細説明**:
  - `project_ref`: Supabaseプロジェクトのリファレンス。Supabase Dashboardで確認できます。
  - `[database]`: データベースに関する設定。
    - `url`: データベース接続URL。
  - `[functions]`: サーバーレス関数に関する設定。
    - `directory`: 関数のディレクトリパス。

#### 2. `migrations/`ディレクトリ

- **役割**: データベーススキーマのマイグレーションファイルを管理。スキーマの変更履歴を追跡し、バージョン管理を容易にします。
- **構造**: 各マイグレーションはタイムスタンプと説明を含むフォルダで管理され、`up.sql`（適用）と`down.sql`（ロールバック）が含まれます。

  ```plaintext
  supabase/migrations/
  ├── 20230427123456_initial_schema/
  │   ├── up.sql
  │   └── down.sql
  └── 20230501120000_add_users_table/
      ├── up.sql
      └── down.sql
  ```

#### 3. `functions/`ディレクトリ

- **役割**: Supabase Functions（サーバーレス関数）を管理。関数ごとにサブディレクトリが作成され、その中にソースコードが配置されます。
- **サンプルコード**:

  ```typescript
  // supabase/functions/my-function/index.ts

  import { serve } from "std/server";

  serve(async (req) => {
    const { name } = await req.json();
    return new Response(`Hello, ${name}!`, {
      headers: { "Content-Type": "text/plain" },
    });
  });
  ```

  **詳細説明**:
  - `index.ts`: 関数のエントリーポイント。リクエストを受け取り、レスポンスを返します。
  - 関数のコードはTypeScriptで記述されており、Supabase CLIを使用してデプロイします。

#### 4. `.env`

- **役割**: 環境変数を定義するファイル。データベース接続情報やSupabaseのURL、APIキーなど機密情報を管理します。
- **サンプルコード**:

  ```env
  # supabase/.env

  SUPABASE_URL=https://xyzcompany.supabase.co
  SUPABASE_ANON_KEY=your-anon-key
  DATABASE_URL=postgres://user:password@localhost:5432/mydb
  ```

### サンプルコード

以下に、主要なディレクトリ・ファイルのサンプルコードを紹介します。

#### マイグレーションファイル (`migrations/`)

**`supabase/migrations/20230427123456_initial_schema/up.sql`**

```sql
-- supabase/migrations/20230427123456_initial_schema/up.sql

-- テーブルの作成
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE profiles (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    bio TEXT,
    avatar_url TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);
```

**`supabase/migrations/20230427123456_initial_schema/down.sql`**

```sql
-- supabase/migrations/20230427123456_initial_schema/down.sql

-- テーブルの削除
DROP TABLE IF EXISTS profiles;
DROP TABLE IF EXISTS users;
```

#### サーバーレス関数ファイル (`functions/`)

**`supabase/functions/my-function/index.ts`**

```typescript
// supabase/functions/my-function/index.ts

import { serve } from "std/server";

serve(async (req) => {
  const { name } = await req.json();
  return new Response(`Hello, ${name}!`, {
    headers: { "Content-Type": "text/plain" },
  });
});
```

#### 環境変数ファイル `.env`

```env
# supabase/.env

SUPABASE_URL=https://xyzcompany.supabase.co
SUPABASE_ANON_KEY=your-anon-key
DATABASE_URL=postgres://user:password@localhost:5432/mydb
```

#### `package.json`

```json
{
  "name": "your-project-name",
  "version": "1.0.0",
  "description": "A Next.js project using Supabase",
  "main": "index.js",
  "scripts": {
    "start": "supabase start",
    "migrate": "supabase db push",
    "deploy:functions": "supabase functions deploy"
  },
  "dependencies": {
    "@supabase/supabase-js": "^2.0.0",
    "next": "latest",
    "react": "latest",
    "react-dom": "latest"
  },
  "devDependencies": {
    "typescript": "^4.0.0",
    "ts-node": "^10.0.0"
  },
  "keywords": [],
  "author": "Your Name",
  "license": "MIT"
}
```

#### アプリケーション側のSupabaseクライアント (`src/utils/supabaseClient.ts`)

```typescript
// src/utils/supabaseClient.ts

import { createClient } from '@supabase/supabase-js';

const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || '';
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || '';

export const supabase = createClient(supabaseUrl, supabaseAnonKey);
```

---

## 環境ごとの設定管理

開発環境（Development）、ステージング環境（Staging）、本番環境（Production）を分けて管理することは、アプリケーションの品質向上やリスク管理において非常に重要です。以下では、Supabase CLIを活用してこれらの環境を適切に分離・管理する方法を詳細に解説します。

### Supabaseプロジェクトの分割

Supabaseでは、各環境ごとに別々のプロジェクトを作成することが推奨されます。これにより、データベースや認証設定などが環境ごとに独立し、安全かつ効率的に管理できます。

1. **Supabase Dashboardにログイン**:  
   [Supabase Dashboard](https://app.supabase.com/)にアクセスし、ログインします。

2. **新しいプロジェクトを作成**:  
   各環境（Development、Staging、Production）に対応するプロジェクトをそれぞれ作成します。プロジェクト名やリソースを分かりやすく命名することをお勧めします（例: `myapp-dev`, `myapp-staging`, `myapp-prod`）。

   ![Supabase Dashboard](https://user-images.githubusercontent.com/your-image-link.png)

3. **各プロジェクトのリファレンスとAPIキーを取得**:  
   各プロジェクトの「Settings」→「API」から、`Project URL`と`anon`キーを取得します。これらは後述する環境変数として使用します。

### 環境ごとの設定ファイルの用意

環境ごとに異なる設定（SupabaseのURLやAPIキー）を管理するために、環境ごとに別々の`.env`ファイルと`config.toml`ファイルを用意します。

#### ディレクトリ構造の例

```plaintext
your-project/
├── supabase/
│   ├── config.development.toml
│   ├── config.staging.toml
│   ├── config.production.toml
│   ├── migrations/
│   ├── functions/
│   ├── .env.development
│   ├── .env.staging
│   └── .env.production
├── src/
├── package.json
└── その他のプロジェクトファイル
```

#### 環境ごとの`.env`ファイルの内容

**`supabase/.env.development`**

```env
SUPABASE_URL=https://your-dev-project.supabase.co
SUPABASE_ANON_KEY=your-dev-anon-key
DATABASE_URL=postgres://user:password@localhost:5432/devdb
```

**`supabase/.env.staging`**

```env
SUPABASE_URL=https://your-staging-project.supabase.co
SUPABASE_ANON_KEY=your-staging-anon-key
DATABASE_URL=postgres://user:password@localhost:5432/stagingdb
```

**`supabase/.env.production`**

```env
SUPABASE_URL=https://your-prod-project.supabase.co
SUPABASE_ANON_KEY=your-prod-anon-key
DATABASE_URL=postgres://user:password@localhost:5432/proddb
```

#### 環境ごとの`config.toml`ファイルの内容

**`supabase/config.development.toml`**

```toml
project_ref = "your-dev-project-ref"

[database]
url = "postgres://user:password@localhost:5432/devdb"

[functions]
directory = "supabase/functions"
```

**`supabase/config.staging.toml`**

```toml
project_ref = "your-staging-project-ref"

[database]
url = "postgres://user:password@localhost:5432/stagingdb"

[functions]
directory = "supabase/functions"
```

**`supabase/config.production.toml`**

```toml
project_ref = "your-prod-project-ref"

[database]
url = "postgres://user:password@localhost:5432/proddb"

[functions]
directory = "supabase/functions"
```

### スクリプトによる環境切り替え

環境ごとに異なる`config.toml`と`.env`ファイルを適用するために、スクリプトを用いて簡単に切り替えられるようにします。`package.json`の`scripts`セクションに以下のスクリプトを追加します。

**`package.json`のスクリプト例**

```json
{
  "scripts": {
    "env:development": "cp supabase/config.development.toml supabase/config.toml && cp supabase/.env.development supabase/.env",
    "env:staging": "cp supabase/config.staging.toml supabase/config.toml && cp supabase/.env.staging supabase/.env",
    "env:production": "cp supabase/config.production.toml supabase/config.toml && cp supabase/.env.production supabase/.env",
    "start:dev": "npm run env:development && supabase start",
    "start:staging": "npm run env:staging && supabase start",
    "start:prod": "npm run env:production && supabase start",
    "migrate:dev": "npm run env:development && supabase db push",
    "migrate:staging": "npm run env:staging && supabase db push",
    "migrate:prod": "npm run env:production && supabase db push",
    "deploy:functions:dev": "npm run env:development && supabase functions deploy",
    "deploy:functions:staging": "npm run env:staging && supabase functions deploy",
    "deploy:functions:prod": "npm run env:production && supabase functions deploy"
  }
}
```

**解説**:
- **環境切り替えスクリプト**:
  - `env:development`, `env:staging`, `env:production`: 各環境に対応する`config.toml`と`.env`ファイルをコピーし、現在の設定を切り替えます。
- **環境ごとの操作**:
  - `start:dev`, `start:staging`, `start:prod`: 各環境に応じてSupabaseのローカル開発サーバーを起動します。
  - `migrate:dev`, `migrate:staging`, `migrate:prod`: 各環境に応じてデータベースマイグレーションを適用します。
  - `deploy:functions:dev`, `deploy:functions:staging`, `deploy:functions:prod`: 各環境に応じてサーバーレス関数をデプロイします。

**使用例**:

```bash
# 開発環境を起動
npm run start:dev

# ステージング環境を起動
npm run start:staging

# 本番環境を起動
npm run start:prod

# 開発環境でマイグレーションを適用
npm run migrate:dev

# ステージング環境でマイグレーションを適用
npm run migrate:staging

# 本番環境でマイグレーションを適用
npm run migrate:prod

# 開発環境で関数をデプロイ
npm run deploy:functions:dev

# ステージング環境で関数をデプロイ
npm run deploy:functions:staging

# 本番環境で関数をデプロイ
npm run deploy:functions:prod
```

**注意点**:
- **ファイルのコピー**: `cp`コマンドはUnix系のシステム（macOS/Linux）で使用できます。Windows環境では、代わりに`copy`コマンドを使用するか、クロスプラットフォーム対応のスクリプトを検討してください。
- **ファイルの整合性**: `config.toml`と`.env`ファイルが正しく対応していることを確認します。誤った設定で操作を行うと、データベース接続エラーや認証エラーが発生する可能性があります。

---

## セキュリティと機密情報の管理

プロジェクトの環境管理において、セキュリティと機密情報の適切な管理は極めて重要です。以下では、環境変数の安全な管理方法とアクセス制御のベストプラクティスについて解説します。

### 環境変数の安全な管理

#### Gitignoreの設定

機密情報を含む`.env`ファイルは、バージョン管理システム（Gitなど）に含めないようにする必要があります。これにより、誤って機密情報が公開されるリスクを防ぎます。

**具体的な手順**:

1. **`.gitignore`ファイルの編集**: プロジェクトのルートディレクトリにある`.gitignore`ファイルを開きます。
2. **`.env`ファイルを追加**: 以下の行を追加して、`.env`ファイルを無視するように設定します。

   ```gitignore
   # 環境変数ファイル
   supabase/.env
   supabase/.env.development
   supabase/.env.staging
   supabase/.env.production
   ```

#### 秘密情報の暗号化

機密情報をより安全に管理するために、暗号化や秘密管理サービスの利用を検討しましょう。

**方法**:

- **暗号化ツールの使用**: `git-crypt`や`BlackBox`などのツールを使用して、機密情報を暗号化します。
- **秘密管理サービスの活用**:
  - **AWS Secrets Manager**: AWS環境でのシークレット管理に最適です。
  - **HashiCorp Vault**: 高度なシークレット管理機能を提供します。
  - **Azure Key Vault**: Microsoft Azure環境でのシークレット管理に適しています。

**例**: GitHub ActionsでSecrets Managerを使用する場合

1. **GitHubリポジトリのSettingsに移動**。
2. **Secrets and variables** → **Actions**を選択。
3. **New repository secret**をクリックし、必要なシークレット（例: `SUPABASE_URL`, `SUPABASE_ANON_KEY`）を追加します。
4. **ワークフロー内でシークレットを参照**:

   ```yaml
   # .github/workflows/deploy.yml
   jobs:
     deploy:
       runs-on: ubuntu-latest
       steps:
         - name: Checkout code
           uses: actions/checkout@v2

         - name: Set up Node.js
           uses: actions/setup-node@v2
           with:
             node-version: '18'

         - name: Install dependencies
           run: npm install

         - name: Deploy to Supabase
           env:
             SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
             SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
           run: npm run deploy:functions:prod
   ```

### アクセス制御

#### 役割ベースのアクセス制御（RBAC）

各環境（開発、ステージング、本番）へのアクセス権限を適切に設定することで、セキュリティを強化します。

**方法**:

1. **ユーザー役割の定義**: 各環境に対して必要な役割（例: 開発者、テスター、運用担当）を定義します。
2. **権限の割り当て**: Supabase Dashboardやクラウドプロバイダーの管理画面を使用して、各ユーザーに適切な権限を割り当てます。

**例**:

- **開発環境**:
  - 開発者にフルアクセス権限を付与。
- **ステージング環境**:
  - テスターに読み取り専用アクセスを付与。
- **本番環境**:
  - 運用担当者のみにフルアクセス権限を付与。

#### Supabaseプロジェクトごとの権限設定

Supabaseでは、各プロジェクトごとにユーザー権限を詳細に設定できます。これにより、各環境に対するアクセス制御が容易になります。

**手順**:

1. **Supabase Dashboardにログイン**。
2. **対象プロジェクトを選択**。
3. **Settings** → **Team**に移動。
4. **ユーザーの招待**や**権限の設定**を行います。

**権限の種類**:

- **Admin**: プロジェクト全体へのフルアクセス権限。
- **Developer**: 開発に必要な権限（例: マイグレーションの適用、関数のデプロイ）。
- **Read-only**: データの閲覧のみ可能。

**ベストプラクティス**:

- **最小権限の原則**: 各ユーザーに必要最低限の権限のみを付与します。
- **定期的な権限見直し**: プロジェクトの進行に応じて、ユーザー権限を定期的に見直します。

---

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

データベーススキーマの変更を効率的かつ安全に管理するために、Supabase CLIを活用したマイグレーションの作成と適用方法を解説します。

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

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

新しいデータベーススキーマの変更を加える際には、マイグレーションファイルを作成します。これにより、スキーマの変更履歴を一貫して管理できます。

```bash
supabase migration new add_profiles_table
```

このコマンドにより、以下のようなディレクトリ構造が作成されます。

```plaintext
supabase/migrations/
└── 20230501120000_add_profiles_table/
    ├── up.sql
    └── down.sql
```

**マイグレーションファイルの内容**:

**`supabase/migrations/20230501120000_add_profiles_table/up.sql`**

```sql
-- supabase/migrations/20230501120000_add_profiles_table/up.sql

CREATE TABLE profiles (
    id SERIAL PRIMARY KEY,
    user_id INTEGER REFERENCES users(id),
    bio TEXT,
    avatar_url TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);
```

**`supabase/migrations/20230501120000_add_profiles_table/down.sql`**

```sql
-- supabase/migrations/20230501120000_add_profiles_table/down.sql

DROP TABLE IF EXISTS profiles;
```

**ポイント**:
- **`up.sql`**: マイグレーションを適用するためのSQLコマンドを記述します。
- **`down.sql`**: マイグレーションをロールバックするためのSQLコマンドを記述します。

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

マイグレーションファイルを編集後、以下のコマンドでマイグレーションを適用します。

```bash
supabase db push
```

**ポイント**:
- `supabase db push`コマンドは、`migrations/`ディレクトリ内のマイグレーションファイルを順番に適用し、データベーススキーマを最新の状態に更新します。
- 適用する際には、現在の環境に対応する`config.toml`と`.env`ファイルが適用されていることを確認してください。

```bash
# 開発環境でマイグレーションを適用
npm run migrate:dev

# ステージング環境でマイグレーションを適用
npm run migrate:staging

# 本番環境でマイグレーションを適用
npm run migrate:prod
```

**注意点**:
- **データの損失**: マイグレーションを適用する前に、特に本番環境ではデータベースのバックアップを取得することを推奨します。
- **マイグレーションの順序**: マイグレーションファイルはタイムスタンプ順に適用されるため、作成順序に注意してください。

### 環境ごとのマイグレーションの適用

環境ごとに異なるデータベースを使用するため、マイグレーションを適用する際にも環境を意識する必要があります。以下の手順でマイグレーションを管理します。

1. **環境を切り替える**:  
   事前に用意したスクリプトを使用して、適用する環境を切り替えます。

   ```bash
   # 開発環境でマイグレーションを適用
   npm run migrate:dev

   # ステージング環境でマイグレーションを適用
   npm run migrate:staging

   # 本番環境でマイグレーションを適用
   npm run migrate:prod
   ```

2. **マイグレーションの適用**:  
   スクリプト内で`supabase db push`が実行され、適切な環境にマイグレーションが適用されます。

**ポイント**:
- **一貫性の確保**: 全ての環境で同じマイグレーションが適用されるようにし、一貫性を保ちます。
- **テストの実施**: ステージング環境でマイグレーションを適用し、問題がないことを確認してから本番環境に適用します。

**ベストプラクティス**:
- **マイグレーションのレビュー**: マイグレーションファイルをチームメンバーと共有し、レビューを行います。
- **段階的なデプロイ**: マイグレーションを段階的にデプロイし、大規模な変更は小さなステップに分けて実施します。

---

## まとめ

Next.jsとSupabase CLIを活用することで、効率的かつ安全に開発環境、ステージング環境、本番環境を管理・運用できます。以下のポイントを押さえておくと、よりスムーズな開発フローを実現できます。

1. **環境ごとに別々のSupabaseプロジェクトを作成**:  
   各環境のデータや設定が独立して管理され、リスクを低減できます。

2. **環境ごとの設定ファイルを用意**:  
   `.env`ファイルや`config.toml`を環境ごとに分けて管理し、誤った設定でデプロイされるリスクを防ぎます。

3. **Supabase CLIの設定を環境ごとに切り替える**:  
   スクリプトを活用して、簡単に環境を切り替えられるようにします。

4. **セキュリティと機密情報の管理**:  
   環境変数の安全な管理やアクセス制御を徹底し、プロジェクトのセキュリティを強化します。

5. **データベースマイグレーションの管理**:  
   マイグレーションを利用して、データベーススキーマの変更を安全かつ効率的に管理します。

**これらの手法を組み合わせることで、Supabaseを用いたNext.jsプロジェクトの複数環境管理がスムーズかつ安全に行えます。** プロジェクトの規模や要件に応じて、適切にカスタマイズ・拡張してください。


https://qiita.com/syukan3/items/1d43efa20cad2f22e2e3

---

## 参考リンク

- [Supabase公式ドキュメント - CLI](https://supabase.com/docs/guides/cli)
- [Supabase公式ドキュメント - 環境設定](https://supabase.com/docs/guides/environment-variables)
- [Next.js公式ドキュメント](https://nextjs.org/docs)
- [Yup - JavaScript Schema Validation](https://github.com/jquense/yup)

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/