本ドキュメントのスコープ
この記事では,Google CloudのCloud SQLをローカルに構築したアプリケーションから利用する方法について解説します.
また,データベース操作にはORM(Object-Relational Mapping)の一つであるPrismaを利用します.
解説すること
- Cloud SQLの設定
- Cloud SQL Proxyを利用したCloud SQLへの接続認証
- ローカル・クラウドの構成
解説しないこと
- ORMとは何か
- Prismaの詳しい利用方法
アーキテクチャの全体像
- ウェブアプリケーション: React.js
- APIサーバ(DBアクセス用): Express.js
- ORM: Prisma
- データベースサーバ: Cloud SQL
- RDBMS: PostgreSQL
- データベース認証: Cloud SQL Auth Proxy
ローカル開発環境は
- macOS 15.1
- apple M2
です.
事前準備1: プロジェクトディレクトリの作成
今回のプロジェクトを格納するディレクトリは次を想定しています(必ずしもこの構成である必要はありません).
demo/ # プロジェクトルート
├── api # DB接続用API
├── app # ウェブアプリケーション
└── proxy # Cloud SQL認証用プロキシ
事前準備2: Cloud SQL データベースの作成,認証設定
Cloud SQL インスタンス・データベースの作成
まず,Google Cloud ConsoleからCloud SQLのインスタンスを作成します.
今回はRDBMSとしてPostgreSQLを選択します.
マシンスペックは実際に構築するシステムのデータ量等を考慮して設定してください.
検証環境として利用する場合は.最低スペック&料金の安いリージョンを選択しましょう.
このとき,接続方式として「パブリックIP」を選択します.
(インスタンス作成後に「接続 > ネットワーキング > インスタンスIPの割り当て」から変更することもできます)
インスタンスが起動したら,データベースを作成します.
接続許可の設定
次に,ローカルのProxyサーバから接続できるようにするための設定を行います.
- 「Cloud SQL Admin API」を有効にします
- サービスアカウントに「Cloud SQL クライアント」のロールを付与します(「IAMと管理 > IAM」に
@developer.gserviceaccount.com
ドメインのサービスアカウントが作成されています) - 「IAMと管理 > サービスアカウント」から,サービスアカウントに紐づいた秘密鍵を作成し,JSONファイルとしてローカルに格納します.
手順1: アプリケーションサーバを立てる(React.js)
アプリ用Reactコード
手始めに,検証用のウェブアプリをReact.jsを使って作成します.
必要なパッケージはあらかじめ導入しておきます.
cd ./app
npx create-next-app@latest # react appの作成
npm install @mui/material @emotion/react @emotion/styled # Material-UI
npm install @axios # HTTPクライアント
npm install @prisma/client # Prisma Client
今回利用するReact.jsコード
以下のコードを./app/src/page.tsx
に記載します.
'use client';
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import {
Box,
Container,
Grid,
Card,
CardContent,
Typography,
TextField,
Checkbox,
Button,
FormControlLabel,
} from '@mui/material';
const API_URL = 'http://localhost:3001'; // APIサーバのエンドポイント
function App() {
const [posts, setPosts] = useState([]);
const [newPost, setNewPost] = useState({ title: '', content: '', published: false });
// Fetch posts
useEffect(() => {
axios.get(`${API_URL}/posts`).then((response) => {
setPosts(response.data);
});
}, []);
// Add new post
const handleSubmit = (e) => {
e.preventDefault();
axios.post(`${API_URL}/posts`, newPost).then((response) => {
setPosts([...posts, response.data]);
setNewPost({ title: '', content: '', published: false });
});
};
return (
<Container maxWidth="md">
<Typography variant="h4" gutterBottom align="center" style={{ marginTop: '2rem' }}>
Create New Post
</Typography>
<form onSubmit={handleSubmit} style={{ marginTop: '1rem', marginBottom: '1rem' }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
label="Title"
fullWidth
value={newPost.title}
onChange={(e) => setNewPost({ ...newPost, title: e.target.value })}
/>
</Grid>
<Grid item xs={12}>
<TextField
label="Content"
multiline
rows={4}
fullWidth
value={newPost.content}
onChange={(e) => setNewPost({ ...newPost, content: e.target.value })}
/>
</Grid>
<Grid item xs={12}>
<FormControlLabel
control={
<Checkbox
checked={newPost.published}
onChange={(e) => setNewPost({ ...newPost, published: e.target.checked })}
/>
}
label="Published"
/>
</Grid>
<Grid item xs={12}>
<Button type="submit" variant="contained" color="primary" fullWidth>
Add Post
</Button>
</Grid>
</Grid>
</form>
<Typography variant="h4" gutterBottom align="center">
Posts
</Typography>
<Grid container spacing={3}>
{posts.map((post) => (
<Grid item xs={12} key={post.id}>
<Box>
<Typography variant="h5" gutterBottom>
{post.title}
</Typography>
<Typography variant="body1">{post.content}</Typography>
</Box>
</Grid>
))}
</Grid>
</Container>
);
}
export default App;
npm run start
などでサーバを起動することができますが,
今はまだAPIサーバ・Proxyサーバの設定が終わっていないのでエラーが生じます.
手順2: Proxyサーバを立てる
次に,APIサーバからのリクエストを受け付け,認証情報とともにCloud SQLに渡すProxyサーバを立てます.
Cloud SQLの接続を「パブリックIP」に設定すると,データベースにアクセスするためには
- 認可済みネットワーク利用する
- Cloud SQL Proxyを経由する
のどちらかの対応を行う必要があります.
今回はCloud SQL Proxyを用いて,プロキシサーバを経由してCloud SQLに接続する方法について説明しています.
Cloud SQL Auth Proxyのダウンロード
Cloud SQL Auth Proxyをダウンロードし実行可能にします.
ダウンロード先はCloud SQL Auth Proxy についてに記載されています.
cd ./proxy
# OSとアーキテクチャに応じて適切なバイナリをダウンロード
curl -o cloud-sql-proxy https://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/v2.6.1/cloud-sql-proxy.{os}.{arch}
chmod +x cloud-sql-proxy
Cloud SQL Auth Proxyの起動
「手順1」でダウンロードしたCloud SQLの秘密鍵のパスを確認し,Cloud SQL Auth Proxyを起動します.
なお,設定するポート番号は,Proxyサーバーがlistenするポート番号です.
例えば--port 5432
に設定すると,APIサーバは0.0.0.0:5432
に向けてリクエストを送信する必要があります.
また,{プロジェクトID}:{リージョン}:{インスタンス名}
はコンソールに表示されている「接続名」と同じです.
./cloud-sql-proxy \
--address 0.0.0.0 \
--port {任意のポート番号} \
--credentials-file {秘密鍵のパス} {プロジェクトID}:{リージョン}:{インスタンス名}
手順3: APIサーバを立てる(Express.js)
Prismaのインストールと初期設定
cd ./api
npm init # npm プロジェクトの初期化
npm install prisma # prismaのインストール
npx prisma init # prismaの初期化
データベース接続情報の設定
APIサーバはProxyサーバにアクセスすることでCloud SQLに接続します.
そのため,データベース接続先は,手順2で設定したProxyサーバのアドレスとポート番号になります.
この情報を.env
に記述します.
DATABASE_URL="postgres://{ユーザー名}:{パスワード}@{IPアドレス}:{ポート}/{データベース名}"
# ex.) "postgres://dailyuser:admin@0.0.0.0:5432/demo-database"
ここでのユーザー名・パスワード・データベース名は,事前準備2で作成したユーザー名とパスワード,作成したデータベースの名称です.
データモデルの定義
利用するデータモデルの定義は./prisma/schema.prisma
に記述します.
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Post {
id Int @id @default(autoincrement())
title String
createdAt DateTime @default(now())
content String?
published Boolean @default(false)
}
記述したデータモデルをSQLに変換
# SQLマイグレーションスクリプトの生成
npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql
./prisma/migration/0_init/migration.sql
に生成されたSQLが格納されています.
-- CreateTable
CREATE TABLE "Post" (
"id" SERIAL NOT NULL,
"title" VARCHAR(255) NOT NULL,
"createdAt" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"content" TEXT,
"published" BOOLEAN NOT NULL DEFAULT false,
);
SQLをCloud SQL データベースに適用
生成されたSQLをクラウド上のデータベースに適用します.
# マイグレーションの適用
npx prisma migrate resolve --applied 0_init
schema.prisma
に変更があった場合はnpx prisma migrate dev --name ${migrade_name}
で変更させることができます.
ウェブアプリの動作確認
手順1で立ち上げたウェブアプリのエンドポイントにアクセスしてみましょう.
タイトルとコンテンツを指定して投稿ができる簡易的なウェブアプリが完成しているはずです.
まとめ
今回は,Google CloudのCloud SQLを,Cloud SQL Auth Proxyを用いてPrisma経由でアクセスする方法を検証・解説しました.
これ以外の接続方法については,今後検証のうえ記事化したいと思っています.