Cloud Run 上の Node.js アプリケーションを Cloud SQL for PostgreSQL データベースに接続する方法

1. 概要

Cloud SQL Node.js コネクタは、Node.js アプリケーションを Cloud SQL データベースに安全に接続する最も簡単な方法です。Cloud Run は、HTTP リクエスト経由で呼び出し可能なステートレス コンテナを実行できるフルマネージドのサーバーレス プラットフォームです。この Codelab では、IAM 認証を使用して、Cloud Run 上の Node.js アプリケーションをサービス アカウントで Cloud SQL for PostgreSQL データベースに安全に接続する方法について説明します。

学習内容

このラボでは、次の方法について学びます。

  • PostgreSQL データベースの Cloud SQL インスタンスを作成する
  • Node.js アプリケーションを Cloud Run にデプロイする
  • Cloud SQL Node.js コネクタ ライブラリを使用してアプリケーションをデータベースに接続する

前提条件

  • このラボは、Cloud コンソールと Cloud Shell 環境に精通していることを前提としています。

2. 始める前に

Cloud プロジェクトのセットアップ

  1. Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Google アカウントをまだお持ちでない場合は、アカウントを作成する必要があります。

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。この設定はいつでも変更できます。
  • プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常は、この内容を意識する必要はありません。ほとんどの Codelab では、プロジェクト ID(通常は PROJECT_ID と識別されます)を参照する必要があります。生成された ID が好みではない場合は、ランダムに別の ID を生成できます。または、ご自身で試して、利用可能かどうかを確認することもできます。このステップ以降は変更できず、プロジェクトを通して同じ ID になります。
  • なお、3 つ目の値として、一部の API が使用するプロジェクト番号があります。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
  1. 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に請求が発生しないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクト全体を削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。

環境設定

検索バーの右にあるアイコンをクリックして、Cloud Shell をアクティブにします。

ecdc43ada29e91b.png

Cloud Shell で、API を有効にします。

gcloud services enable compute.googleapis.com sqladmin.googleapis.com \
  run.googleapis.com artifactregistry.googleapis.com \
  cloudbuild.googleapis.com servicenetworking.googleapis.com

承認を求められたら、[承認] をクリックして続行します。

6356559df3eccdda.png

このコマンドが完了するまで数分かかる場合がありますが、最終的には次のような成功メッセージが表示されます。

Operation "operations/acf.p2-327036483151-73d90d00-47ee-447a-b600-a6badf0eceae" finished successfully.

3. サービス アカウントを設定する

Cloud Run で使用する Google Cloud サービス アカウントを作成して構成し、Cloud SQL に接続するための適切な権限を付与します。

  1. 次のように gcloud iam service-accounts create コマンドを実行して、新しいサービス アカウントを作成します。
    gcloud iam service-accounts create quickstart-service-account \
      --display-name="Quickstart Service Account"
    
  2. 次の gcloud projects add-iam-policy-binding コマンドを実行して、作成した Google Cloud サービス アカウントに Cloud SQL クライアント ロールを追加します。Cloud Shell では、式 ${GOOGLE_CLOUD_PROJECT} はプロジェクトの名前に置き換えられます。手動で交換することもできます。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/cloudsql.client"
    
  3. 次のように gcloud projects add-iam-policy-binding コマンドを実行して、作成した Google Cloud サービス アカウントに Cloud SQL インスタンス ユーザーのロールを追加します。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/cloudsql.instanceUser"
    
  4. 次のように gcloud projects add-iam-policy-binding コマンドを実行して、作成した Google Cloud サービス アカウントにログ書き込みのロールを追加します。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

4. Cloud SQL を設定する

gcloud sql instances create コマンドを実行して、Cloud SQL インスタンスを作成します。

  • --database-version: データベース エンジンのタイプとバージョン。指定しない場合は、API のデフォルトが使用されます。現在利用可能なバージョンを確認するには、gcloud database versions ドキュメントをご覧ください。
  • --cpu: マシンに必要なコア数。
  • --memory: マシンに必要なメモリ量を示す整数値。サイズ単位を指定する必要があります(例: 3, 072 MB、9 GB)。単位を指定しない場合、GB が使用されます。
  • --region: インスタンスのリージョンのロケーション(us-central1、asia-east1、us-east1 など)。
  • --database-flags: フラグの設定を許可します。この場合、cloudsql.iam_authentication を有効にして、Cloud Run が以前に作成したサービス アカウントを使用して Cloud SQL に接続できるようにします。
    gcloud sql instances create quickstart-instance \
      --database-version=POSTGRES_18 \
      --tier=db-custom-1-3840 \
      --region=us-central1 \
      --edition=ENTERPRISE \
      --database-flags=cloudsql.iam_authentication=on
    

このコマンドが完了するまで数分かかることがあります。

gcloud sql databases create コマンドを実行して、quickstart-instance 内に Cloud SQL データベースを作成します。

gcloud sql databases create quickstart_db \
  --instance=quickstart-instance

先ほど作成したサービス アカウントの PostgreSQL データベース ユーザーを作成して、データベースにアクセスします。

gcloud sql users create quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam \
  --instance=quickstart-instance \
  --type=cloud_iam_service_account \
  --database-roles=postgres

警告: 本番環境のアプリケーションでは --database-roles=postgres を使用しないでください。これは、このラボのコードでテーブルをプログラムで作成および削除するために必要な権限を提供するために使用されます。

5. アプリケーションを準備する

HTTP リクエストに応答する Node.js アプリケーションを準備します。

  1. Cloud Shell で、helloworld という名前の新しいディレクトリを作成し、そのディレクトリに移動します。
    mkdir helloworld
    cd helloworld
    
  2. package.json ファイルをモジュールとして初期化します。
    npm init -y
    npm pkg set type="module"
    npm pkg set main="index.mjs"
    npm pkg set scripts.start="node index.mjs"
    
  3. Cloud SQL Node.js コネクタの依存関係をインストールします。
    npm install @google-cloud/cloud-sql-connector
    
  4. PostgreSQL データベースを操作するには、pg をインストールします。
    npm install pg
    
  5. 着信 HTTP リクエストを受け入れるために express をインストールします。
    npm install express
    
  6. アプリケーション コードを含む index.mjs ファイルを作成します。このコードは次の操作を行うことができます。
    • HTTP リクエストを受け入れる
    • データベースに接続する
    • データベースに HTTP リクエストの時刻を保存する
    • 最後の 5 件のリクエストの時刻を返す
    Cloud Shell で次のコマンドを実行します。
    cat > index.mjs << "EOF"
    import express from 'express';
    import pg from 'pg';
    import {Connector} from '@google-cloud/cloud-sql-connector';
    
    const {Pool} = pg;
    
    const connector = new Connector();
    const clientOpts = await connector.getOptions({
        instanceConnectionName: process.env.INSTANCE_CONNECTION_NAME,
        authType: 'IAM'
    });
    
    const pool = new Pool({
        ...clientOpts,
        user: process.env.DB_USER,
        database: process.env.DB_NAME
    });
    
    const app = express();
    
    app.get('/', async (req, res) => {
      await pool.query('INSERT INTO visits(created_at) VALUES(NOW())');
      const {rows} = await pool.query('SELECT created_at FROM visits ORDER BY created_at DESC LIMIT 5');
      console.table(rows); // prints the last 5 visits
      res.send(rows);
    });
    
    const port = parseInt(process.env.PORT) || 8080;
    app.listen(port, async () => {
      console.log('process.env: ', process.env);
      await pool.query(`CREATE TABLE IF NOT EXISTS visits (
        id SERIAL NOT NULL,
        created_at timestamp NOT NULL,
        PRIMARY KEY (id)
      );`);
      console.log(`helloworld: listening on port ${port}`);
    });
    
    EOF
    

このコードは、PORT 環境変数で定義されたポートをリッスンする基本的なウェブサーバーを作成します。これで、アプリケーションをデプロイする準備が整いました。

6. Cloud Run アプリケーションをデプロイする

次のコマンドを実行して、アプリケーションを Cloud Run にデプロイします。

  • --region: インスタンスのリージョンのロケーション(us-central1、asia-east1、us-east1 など)。
  • --source: デプロイするソースコード。この場合、. は現在のフォルダ helloworld のソースコードを指します。
  • --set-env-vars: アプリケーションが Cloud SQL データベースにアクセスするために使用する環境変数を設定します。
  • --service-account: この Codelab の冒頭で作成した Cloud SQL データベースに接続する権限を持つサービス アカウントに Cloud Run デプロイを関連付けます。
  • --allow-unauthenticated: 未認証のリクエストを許可して、インターネットからアプリケーションにアクセスできるようにします。
gcloud run deploy helloworld \
  --region=us-central1 \
  --source=. \
  --set-env-vars INSTANCE_CONNECTION_NAME="${GOOGLE_CLOUD_PROJECT}:us-central1:quickstart-instance" \
  --set-env-vars DB_NAME="quickstart_db" \
  --set-env-vars DB_USER="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam" \
  --service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
  --allow-unauthenticated

続行するかどうかを確認するメッセージが表示されたら、yEnter を押します。

Do you want to continue (Y/n)? y

数分後、アプリケーションからアクセス可能な URL が提供されます。

URL に移動して、アプリケーションの動作を確認します。URL にアクセスするか、ページを更新するたびに、最近の 5 回のアクセスが JSON として返されます。

7. 完了

Cloud SQL で実行されている PostgreSQL データベースに接続できる Node.js アプリケーションを Cloud Run にデプロイしました。

学習した内容

  • Cloud SQL for PostgreSQL データベースを作成する
  • Cloud Run への Node.js アプリケーションのデプロイ
  • Cloud SQL Node.js コネクタを使用してアプリケーションを Cloud SQL に接続する

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。プロジェクト全体を削除する場合は、次のコマンドを実行します。

gcloud projects delete ${GOOGLE_CLOUD_PROJECT}