🐌

Cloud Run をローカルで動作確認する

2024/06/28に公開

概要

Cloud Code プラグインを使用して、ローカル端末の IDE 上で Cloud Run の動作確認を行います。

想定読者

  • VSCode や JetBrains製IDE での Python 開発経験のある方
  • Docker コンテナを触ったことのある方

環境

ローカル端末

  • OS: macOS Sonoma 14.4.1
  • チップ: Apple M3 Max
  • IDE: PyCharm 2024.1.3
  • Homebrew 4.3.7
  • Google Cloud SDK: 481.0.0
  • Docker Desktop: 4.30.0
  • Python: 3.11.4

Cloud Code とは

IntelliJ などの JetBrains製IDE や VSCode の拡張機能としてインストールできるプラグインです。
今回紹介する Cloud Run のローカル動作確認以外にも、Cloud Run のデプロイや Cloud Storage のバケットなどを IDE 上から直接参照することが可能です。
https://cloud.google.com/code

IDE 内で Cloud Code エミュレータ上にコンテナイメージを走らせることで、ローカルで Cloud Run の動作確認が実施できます。
今回は JetBrains製IDE である PyCharm に Cloud Code プラグインをインストールしてみます。

Cloud Code プラグインのインストール

https://cloud.google.com/code/docs/intellij/install
公式サイトの手順に沿って Cloud Code プラグインを PyCharm にインストールします。

JetBrains製IDE を使用する際の注意点として、バージョンは 2022.3 以降、かつ下記のIDEである必要があります。 ※PhpStorm や RustRover は未対応

  • IntelliJ Ultimate または Community
  • PyCharm Professional または Community
  • WebStorm
  • GoLand

ちなみに、VSCode 版のインストール手順は下記になります。
https://cloud.google.com/code/docs/vscode/install

1. プラグインのインストール

  1. Marketplace の検索ボックスに Cloud Code と入力します。
  2. 検索結果から「Gemini Code Assist/Cloud Code」をインストールします。
  3. インストールが終わったら IDE を再起動します。

    ※上記は Japanese Language Pack プラグインを導入している PyCharm の画像です。

2. Cloud Code の依存関係を設定

  1. PyCharm の設定画面を開き、[ツール] > [Gemini + Google Cloud Code] > [Dependencies] を開きます。
  2. Cloud SDK の欄で、 Use a custom local installation ラジオボタンを選択し、ローカル端末にインストールしている Google Cloud SDK のパスを入力します。
    ※私の環境では何故か Allow the plugin to manage and install the Cloud SDK ラジオボタンを選択した際に表示される Install ボタンを押下しても上手くいきませんでした…😿

Google Cloud SDK のパスはwhichコマンドなどで確認できます。
私は Homebrew 経由でインストールしたので、パスが/opt/homebrew配下となっています。

$ which gcloud
/opt/homebrew/share/google-cloud-sdk/bin/gcloud

Cloud Run にデプロイする資材(Python)の準備

Cloud Run にデプロイする予定の main.pyrequirements.txt、およびDockerfileを用意します。

# フォルダ構成
cloud-run-test
├── main.py
├── requirements.txt
└── Dockerfile
main.py
import logging
import os

from cloudevents.http import from_http
from flask import Flask, request
from google.cloud import logging as cloud_logging

app = Flask(__name__)


@app.route("/", methods=["POST"])
def index():
    event = from_http(request.headers, request.data)
    data = event.get_data()

    bucket_name = data.get('bucket')
    object_path = data.get('name')

    project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
    location = os.environ.get("REGION")
    message = os.environ.get("MESSAGE")

    logger = setup_logger(__name__)

    logger.info(f"""
        bucket_name: {bucket_name}
        object_path: {object_path}
        project_id: {project_id}
        location: {location}
        message: {message}
    """)

    return message, 200


def setup_logger(log_name: str = None, log_level: str = logging.DEBUG) -> logging.Logger:
    logging.basicConfig(
        format="[%(asctime)s][%(levelname)s] %(message)s",
        level=logging.INFO
    )
    logger = logging.getLogger(log_name)

    cloud_logging.Client().setup_logging()
    logger.setLevel(log_level)

    return logger


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
requirements.txt
Flask==3.0.3
gunicorn==22.0.0
cloudevents==1.10.1
google-cloud-logging==3.9.0
Dockerfile
FROM python:3.11-slim

# Cloud Run のログに、ステートメントとログメッセージが即座に出力されるようにする
ENV PYTHONUNBUFFERED True

# requirements.txt をコードと別にコピーすることで、コードの変更毎に pip install が再実行されるのを防止
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# ローカルのコードをコンテナイメージにコピー
ENV APP_HOME /app
WORKDIR $APP_HOME
COPY . ./

# gunicon を使って、Flask アプリケーションを起動
CMD exec gunicorn --bind :$PORT --workers 1 --threads 1 --timeout 0 main:app

実際の運用では、指定の Cloud Storage バケットにファイルがアップロードされたのを契機に Eventarc トリガーが発火して Cloud Run を実行するイメージです。

Cloud Run をローカルで実行する実行構成の構築

  1. PyCharm の右上にあるナビゲーションバーから、実行構成の編集を押下します。
  2. 左上の + アイコンを押下し、新規構成の追加から [Cloud Code: Cloud Run] > [Run Locally] を選択します。
  3. 実行構成の名前を入力します。今回は公式ガイドと同じ「Cloud Run: Run Locally」にしました。
  4. Advanced Docker settings 折りたたみアイコンを押下し、Docker Environment 入力欄に--platform=linux/amd64を設定します。
    ※Apple Silicon Mac で Docker Build する際に必要な対応。詳細はこちらを参照

    ちなみに On file save を選択すると、Pythonコードを修正して保存した際に自動でコンテナイメージが再デプロイされます。修正結果をすぐに確認したい場合はこちらが便利です。
  5. Advanced revision settings 折りたたみアイコンを押下し、Environment Variables 入力欄に環境変数を設定します。

    ここで設定した環境変数は、main.pyの下記処理で取得されます。
    location = os.environ.get("REGION")
    message = os.environ.get("MESSAGE")
  1. 実行/デバッグ構成画面右下の OK ボタンを押下します。

Cloud Run を Cloud Code エミュレータでローカル起動する

1. エミュレータの起動

  1. PyCharm の右上にあるナビゲーションバーから、右向三角アイコンを押下し、Cloud Run: Run Locally を実行します。
  2. Cloud Run をローカル起動した旨が通知されたら成功です。

2. ローカルの Cloud Run にリクエストを送信

  1. ターミナルから、curlコマンドを使用してリクエストを送信してみます。data属性内の値が CloudEvents のデータ部分 になります。
    • name: Cloud Storage バケットにアップロードされたオブジェクトのパス
    • bucket: 対象の Cloud Storage バケット名
    $ curl -X POST localhost:8080 \
        -H "Content-Type: application/cloudevents+json; charset=utf-8" \
        -d '{
               "specversion" : "1.0",
               "type" : "google.cloud.storage.object.v1.finalized",
               "source" : "//storage.googleapis.com/projects/_/buckets/landing-bucket-abaq-trial",
               "subject" : "123",
               "id" : "A234-1234-1234",
               "time" : "2018-04-05T17:31:00Z",
               "data" : {
                          "name": "test_dir/sample__20240627.csv",
                          "bucket": "landing-bucket-abaq-trial"
               }
        }'
  1. リクエストしたdata属性の値と、実行構成で設定した環境変数の値がログ出力されています。

    main.pyの下記処理が正常に実行されたことを確認できました。
main.py
@app.route("/", methods=["POST"])
def index():
    event = from_http(request.headers, request.data)
    data = event.get_data()

    bucket_name = data.get('bucket')
    object_path = data.get('name')

    project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")
    location = os.environ.get("REGION")
    message = os.environ.get("MESSAGE")

    logger = setup_logger(__name__)

    logger.info(f"""
        bucket_name: {bucket_name}
        object_path: {object_path}
        project_id: {project_id}
        location: {location}
        message: {message}
    """)

    return message, 200

備考

  1. 今回のPythonコードと Dockerfile 作成の参考にしました。
  2. Cloud Code プラグインをインストールした後、下記コマンドで Google Cloud SDK の認証を行う必要があるかもしれません。
# gcloud auth login & gcloud auth application-default login
$ gcloud auth login --update-adc

Discussion