Cloud SQL for PostgreSQL を使用して JavaScript アプリケーションを Cloud Run にデプロイする

1. 概要

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

学習内容

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

  • Cloud SQL for PostgreSQL インスタンスを作成する
  • Cloud SQL データベースに接続するアプリケーションを Cloud Run にデプロイする

学習内容

  • Cloud SQL for PostgreSQL インスタンスを作成する
  • Cloud SQL データベースに接続するアプリケーションを Cloud Run にデプロイする

2. 前提条件

  1. Google アカウントをお持ちでない場合は、Google アカウントを作成する必要があります。
    • 仕事用または学校用アカウントではなく、個人アカウントを使用します。職場用アカウントと学校用アカウントには、このラボに必要な API を有効にできない制限が設定されている場合があります。

3. プロジェクトの設定

  1. Google Cloud コンソールにログインします。
  2. Cloud コンソールで課金を有効にします
    • このラボを完了するのにかかる Cloud リソースの費用は 1 米ドル未満です。
    • このラボの最後の手順に沿ってリソースを削除すると、それ以上の料金は発生しません。
    • 新規ユーザーは、300 米ドル分の無料トライアルをご利用いただけます。
  3. 新しいプロジェクトを作成するか、既存のプロジェクトを再利用します。

4. Cloud Shell エディタを開く

  1. Cloud Shell エディタに移動します。
  2. ターミナルが画面の下部に表示されない場合は、ターミナルを開きます。
    • ハンバーガー メニュー ハンバーガー メニュー アイコン をクリックします。
    • [Terminal] をクリックします。
    • [New Terminal] をクリックします。Cloud Shell エディタで新しいターミナルを開く
  3. ターミナルで、次のコマンドを使用してプロジェクトを設定します。
    • 形式:
      gcloud config set project [PROJECT_ID]
      
    • 例:
      gcloud config set project lab-project-id-example
      
    • プロジェクト ID を忘れた場合:
      • 次のコマンドを使用すると、すべてのプロジェクト ID を一覧表示できます。
        gcloud projects list | awk '/PROJECT_ID/{print $2}'
        
      Cloud Shell エディタのターミナルでプロジェクト ID を設定する
  4. 承認を求められたら、[承認] をクリックして続行します。Cloud Shell を承認する
  5. 次のようなメッセージが表示されます。
    Updated property [core/project].
    
    WARNING が表示され、Do you want to continue (Y/N)? と表示された場合は、プロジェクト ID が正しく入力されていない可能性があります。N を押して Enter を押し、gcloud config set project コマンドをもう一度実行してみてください。

5. API を有効にする

ターミナルで API を有効にします。

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

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

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

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

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

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 サービス アカウントにログ書き込みのロールを追加します。
    gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
      --member="serviceAccount:quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --role="roles/logging.logWriter"
    

7. Cloud SQL データベースを作成する

  1. Private Service Connect を使用して Cloud Run から Cloud SQL へのネットワーク接続を許可するサービス接続ポリシーを作成する
    gcloud network-connectivity service-connection-policies create quickstart-policy \
        --network=default \
        --project=${GOOGLE_CLOUD_PROJECT} \
        --region=us-central1 \
        --service-class=google-cloud-sql \
        --subnets=https://www.googleapis.com/compute/v1/projects/${GOOGLE_CLOUD_PROJECT}/regions/us-central1/subnetworks/default
    
  2. データベースの固有のパスワードを生成する
    export DB_PASSWORD=$(openssl rand -base64 20)
    
  3. gcloud sql instances create コマンドを実行して Cloud SQL インスタンスを作成する
    gcloud sql instances create quickstart-instance \
        --project=${GOOGLE_CLOUD_PROJECT} \
        --root-password=${DB_PASSWORD} \
        --database-version=POSTGRES_17 \
        --tier=db-perf-optimized-N-2 \
        --region=us-central1 \
        --ssl-mode=ENCRYPTED_ONLY \
        --no-assign-ip \
        --enable-private-service-connect \
        --psc-auto-connections=network=projects/${GOOGLE_CLOUD_PROJECT}/global/networks/default
    

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

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

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

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. PostgreSQL データベースを操作するには、pg をインストールします。
    npm install pg
    
  4. 着信 HTTP リクエストを受け入れるために express をインストールします。
    npm install express
    
  5. アプリケーション コードを含む index.mjs ファイルを作成します。このコードは次の操作を行うことができます。
    • HTTP リクエストを受け入れる
    • データベースに接続する
    • データベースに HTTP リクエストの時刻を保存する
    • 最後の 5 件のリクエストの時刻を返す
    Cloud Shell で次のコマンドを実行します。
    cat > index.mjs << "EOF"
    import express from 'express';
    import pg from 'pg';
    const { Pool } = pg;
    
    const pool = new Pool({
      host: process.env.DB_HOST,
      user: process.env.DB_USER,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_NAME,
      ssl: {
        require: true,
        rejectUnauthorized: false, // required for self-signed certs
        // https://node-postgres.com/features/ssl#self-signed-cert
      }
    });
    
    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 環境変数で定義されたポートをリッスンする基本的なウェブサーバーを作成します。これで、アプリケーションをデプロイする準備が整いました。

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

  1. 次のコマンドを実行して、アプリケーションを Cloud Run にデプロイします。
    gcloud run deploy helloworld \
      --region=us-central1 \
      --source=. \
      --set-env-vars DB_NAME="quickstart_db" \
      --set-env-vars DB_USER="postgres" \
      --set-env-vars DB_PASSWORD=${DB_PASSWORD} \
      --set-env-vars DB_HOST="$(gcloud sql instances describe quickstart-instance --project=${GOOGLE_CLOUD_PROJECT} --format='value(settings.ipConfiguration.pscConfig.pscAutoConnections.ipAddress)')" \
      --service-account="quickstart-service-account@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
      --network=default \
      --subnet=default \
      --allow-unauthenticated
    
  2. 続行するかどうかを確認するメッセージが表示されたら、YEnter を押します。
    Do you want to continue (Y/n)? Y
    

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

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

10. 完了

このラボでは、以下の操作について学習しました。

  • Cloud SQL for PostgreSQL インスタンスを作成する
  • Cloud SQL データベースに接続するアプリケーションを Cloud Run にデプロイする

クリーンアップ

Cloud SQL には無料枠がないため、引き続き使用すると課金されます。Cloud プロジェクトを削除して、追加料金が発生しないようにすることができます。

サービスが使用されていない場合、Cloud Run の料金は発生しませんが、コンテナ イメージを Artifact Registry に保存すると課金される場合があります。Cloud プロジェクトを削除すると、そのプロジェクト内で使用されているすべてのリソースに対する課金が停止します。

必要に応じて、プロジェクトを削除します。

gcloud projects delete $GOOGLE_CLOUD_PROJECT

cloudshell ディスクから不要なリソースを削除することもできます。次のことが可能です。

  1. Codelab プロジェクト ディレクトリを削除します。
    rm -rf ~/task-app
    
  2. 警告: この操作は元に戻せません。Cloud Shell のすべてのデータを削除して空き容量を増やす場合は、ホーム ディレクトリ全体を削除できます。残しておきたいものはすべて別の場所に保存されていることを確認してください。
    sudo rm -rf $HOME
    

学習を継続