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. pg をインストールして、PostgreSQL データベースを操作します。
    npm install pg
    
  4. express をインストールして、受信 HTTP リクエストを受け入れます。
    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
    

学習を継続