はじめに
少し前に話題になっていた Supabase を最近になって知りました。
SupabaseはFirebaseの代替手段と謳っており、Postgresのデータベースや認証、ストレージなどの機能を提供するプラットフォームのことです。
個人的にPosrgresデータベースを無料枠で使用することができる点が素晴らしいと思っています。
FirebaseのNoSQLもいいですが、EntityFrameworkとの相性は悪くて開発体験がよくないですから、あまり使いたくはありません。また、Cloud SQLや RDSのようなフルマネージドデータベースを使用するという選択肢もありますが、いかんせんコストが高いので、個人開発には向きません。
そんなこんなでCloudRun + Supabaseを使用すれば、実質無料で.NETの環境を作ることができるのではないかと思って、試してみました。
インフラ
- Cloud Run
- Supabase (Postgres)
環境
- Docker
- .NET MVC Identity
- Postgres
Supabaseでプロジェクト作成
ログインは割愛します。
まず、プロジェクトを作成します。(データベースパスワードは控えておく)
プロジェクトを作成してプロジェクト詳細に入ったら、左メニューの設定(Project Settings)>Databaseに移動します。
Connection stringの.NETタブを選択すると.NETアプリ用の接続設定を取得できます。
この時点でSQLクライアントソフトから接続確認ができました。
.NET Core Identity環境の作成
.NETの環境を作成します。
開発環境はVSCodeでDev Container拡張機能を使用します。
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS runtime
WORKDIR /app
COPY ./src .
RUN apt-get update && apt-get install -y \
git \
vim
RUN dotnet tool install --global dotnet-ef --version 7.0
RUN dotnet tool install --global dotnet-aspnet-codegenerator --version 7.0
ENV PATH $PATH:/root/.dotnet/tools
ENV TZ Asia/Tokyo
version: '3.7'
services:
supabase_web:
container_name: "supabase_web"
build:
context: ./
dockerfile: Dockerfile
ports:
- "50001:8080"
working_dir: /app/
tty: true
volumes:
- ./src/:/app/
supabase_db:
container_name: "supabase_db"
image: postgres:13-bullseye
ports:
- "55432:5432"
volumes:
- .dbstore:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=A9AbbsJiNXUA
mkdir src
でsrcフォルダを作成したあとに、コマンドパレットを開き、>Dev Containers: Open Folder in Container...
を実行してコンテナを起動します。
次に、下記コマンドで.NET MVCテンプレートを作成します。
cd /
dotnet new mvc --auth Individual -uld -o app -n SupabaseTest
併せて、gitignoreファイルも作成します。
cd /app && dotnet new gitignore
作成したら、下記コマンドでPostgresのNugetパッケージをインストールします。
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
PostgreSQLに接続できるようにProgram.cs
ファイルを編集します。
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using SupabaseTest.Data;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("http://0.0.0.0:8080");
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(connectionString));
// 略 //
また、appSettings.Develop.json
を以下のように変更します。
{
"DetailedErrors": true,
"ConnectionStrings": {
"DefaultConnection": "Host= supabase_db;Port=5432;Database=postgres;Username=postgres;Password=A9AbbsJiNXUA"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
次にマイグレーション関連を整理します。
今のままではマイグレーションがSQL Server用のものとなっており、updateを行ってもエラーが発生します。そのため、下記コマンドで初期マイグレーションを再発行します。
cd /app
rm Data/Migrations/*.cs
# マイグレーションの発行
dotnet ef migrations add InitialCreate --context ApplicationDbContext --output-dir Data/Migrations
# マイグレーションをデータベースに反映
dotnet ef database update --context ApplicationDbContext
次にデバッグできるようにVSCodeの左メニューから、「実行とデバッグ」を開き、「launch.jsonファイルを作成」し、.NET 5+ .NET MVCを選択してlaunch.json
を自動生成します。
また、VSCodeの拡張機能で「C# ms-dotnettools.csharp
」をインストールしておきます。
launch.json
ファイルが自動生成できたら、F5
キーを押してデバッグを開始します。
デバッグが実行出来たら、http://localhost:50001/ でアクセスできます。
データベースに接続できているか確認するために適当にユーザーを登録して、「Click here to confirm your account」をクリックします。その後、ログインができていたらDBは接続できています。
これでローカルで開発できる環境ができました。
本番環境にマイグレーション
CloudRunにデプロイした際にSupabaseのPostgreに接続できるようにする必要があります。
まず、Postgresの接続情報を記載したappsettings.Production.json
を作成します。
{
"DetailedErrors": false,
"ConnectionStrings": {
"DefaultConnection": "User Id=postgres;Password=XXXXXXXX;Server=db.xxxxxxxxxxxxxxxxxx.supabase.co;Port=5432;Database=postgre"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
次に下記のコマンドでsupabaseのデータベースを更新します。
cd /app
export ASPNETCORE_ENVIRONMENT="Production"
dotnet ef database update
export ASPNETCORE_ENVIRONMENT="Development"
Cloud Runにデプロイ
まず、Cloud Runとは、サーバーレスのプラットフォームで、コンテナベースのWebアプリケーションを実行させることができます。
要はDockerなどのコンテナからアプリケーションを実行するため、任意の言語の環境を使用することができます。また、Dockerベースの開発をする場合、ローカルの環境とCloud Runの環境を同じ環境にすることができるメリットがあります。
先ほど作成した.NETアプリケーションをCloud Runにデプロイします。
GCPのロール変更
GCPのサービスアカウントからCloudRunにデプロイするため、権限を付与する必要があります。
- Cloud Buildに移動して、左メニューの「設定」に移動
- 「Cloud Run」のステータスを有効に変更
- モーダルの「すべてのサービス アカウントにアクセス権を付与」
Cloud buildでイメージをビルドする
gcloud sdkがローカルにインストールされている前提で話します。
Cloud Runでデプロイするためにはデプロイするコンテナのイメージが必要なので、Cloud Buildを使用してCloud Registryにイメージを保存します。
まず、デプロイ用のDocker設定ファイルであるCloudRun.Dockerfile
を作成します。
注意点としては、CloudRunにデプロイする場合は 必ず8080ポートを公開することです。そうしないとデプロイ時にエラーが発生します。
FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /app
COPY ./src .
RUN dotnet publish -c Release -o dist
FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS runtime
WORKDIR /app
COPY --from=build /app/dist .
ENV TZ Asia/Tokyo
ENV ASPNETCORE_ENVIRONMENT Production
ENV PORT=8080
EXPOSE 8080
ENTRYPOINT ["dotnet", "SupabaseTest.dll"]
次にビルド設定のcloudbuild.yml
を作成します。
steps:
# Build the container image
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/PROJECT_ID/IMAGE', '-f', 'CloudRun.Dockerfile', '.']
# Push the container image to Container Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/PROJECT_ID/IMAGE']
# Deploy container image to Cloud Run
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud
args: ['run', 'deploy', 'SERVICE_NAME', '--image', 'gcr.io/PROJECT_ID/IMAGE', '--region', 'REGION', '--allow-unauthenticated']
images:
- gcr.io/PROJECT_ID/IMAGE
cloudbuild.yml
の各項目を変換しておいてください。
変換前 | 内容 |
---|---|
PROJECT_ID |
プロジェクトのID |
IMAGE |
Contaier Registoryに保存する名前 |
SERVICE_NAME |
デプロイサービスの名前 |
REGION |
デプロイ先のリージョン 東京なら asia-northeast1 |
デプロイする
ローカル環境でCloudRun.Dockerfile
のあるフォルダで以下のコマンドを実行します。
gcloud builds submit ./ --config cloudbuild.yml
特にエラーがなければデプロイの成功です。
認証の機能が使用できていたので、データベースにも接続できていますね!
おわりに
実際にCloud RunとSupabaseを使用することで.NETの環境を限りなく安くなるように作成できました。ただ、今回作成した.NETアプリは、Cloud Runの特性上、十数分程度でログインセッションが切れてしまうため、セッションをインメモリからデータベースに保存するなどの対応が必要になりそうです。
Supabaseのプロジェクトは無料枠で2つのみなので、数を作成できませんが、個人開発にはもっていこいのサービスだと思います。
Cloud Runなので.NET Coreの環境にとどまらず、頑張ればWordpressの環境も作成できるんじゃないかと思います。ほぼ無料でWordpress環境は夢があっていいですね。
さいごに、サクッと記事が書けるだろうと思って書き始めましたが、思ったより基本的な説明に時間をとってしまう形になってしまいました。記事を作成するのは難しいですね...