🐌
Cloud Run をローカルで動作確認する
概要
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 上から直接参照することが可能です。
IDE 内で Cloud Code エミュレータ上にコンテナイメージを走らせることで、ローカルで Cloud Run の動作確認が実施できます。
今回は JetBrains製IDE である PyCharm に Cloud Code プラグインをインストールしてみます。
Cloud Code プラグインのインストール
公式サイトの手順に沿って Cloud Code プラグインを PyCharm にインストールします。
JetBrains製IDE を使用する際の注意点として、バージョンは 2022.3 以降、かつ下記のIDEである必要があります。 ※PhpStorm や RustRover は未対応
- IntelliJ Ultimate または Community
- PyCharm Professional または Community
- WebStorm
- GoLand
ちなみに、VSCode 版のインストール手順は下記になります。
1. プラグインのインストール
- Marketplace の検索ボックスに Cloud Code と入力します。
- 検索結果から「Gemini Code Assist/Cloud Code」をインストールします。
- インストールが終わったら IDE を再起動します。
※上記は Japanese Language Pack プラグインを導入している PyCharm の画像です。
2. Cloud Code の依存関係を設定
- PyCharm の設定画面を開き、[ツール] > [Gemini + Google Cloud Code] > [Dependencies] を開きます。
- 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.py
とrequirements.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 をローカルで実行する実行構成の構築
- PyCharm の右上にあるナビゲーションバーから、実行構成の編集を押下します。
- 左上の + アイコンを押下し、新規構成の追加から [Cloud Code: Cloud Run] > [Run Locally] を選択します。
- 実行構成の名前を入力します。今回は公式ガイドと同じ「Cloud Run: Run Locally」にしました。
-
Advanced Docker settings 折りたたみアイコンを押下し、Docker Environment 入力欄に
--platform=linux/amd64
を設定します。
※Apple Silicon Mac で Docker Build する際に必要な対応。詳細はこちらを参照
ちなみに On file save を選択すると、Pythonコードを修正して保存した際に自動でコンテナイメージが再デプロイされます。修正結果をすぐに確認したい場合はこちらが便利です。
-
Advanced revision settings 折りたたみアイコンを押下し、Environment Variables 入力欄に環境変数を設定します。
ここで設定した環境変数は、main.py
の下記処理で取得されます。
location = os.environ.get("REGION")
message = os.environ.get("MESSAGE")
- 実行/デバッグ構成画面右下の OK ボタンを押下します。
Cloud Run を Cloud Code エミュレータでローカル起動する
1. エミュレータの起動
- PyCharm の右上にあるナビゲーションバーから、右向三角アイコンを押下し、Cloud Run: Run Locally を実行します。
- Cloud Run をローカル起動した旨が通知されたら成功です。
2. ローカルの Cloud Run にリクエストを送信
- ターミナルから、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"
}
}'
- リクエストした
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
備考
- 今回のPythonコードと Dockerfile 作成の参考にしました。
- Cloud Code プラグインをインストールした後、下記コマンドで Google Cloud SDK の認証を行う必要があるかもしれません。
# gcloud auth login & gcloud auth application-default login
$ gcloud auth login --update-adc
Discussion