ビルドなしでCloud Runサービスをソースコードからデプロイしてみた – G-gen Tech Blog

G-gen の杉村です。当記事では、Google Cloud のフルマネージドなコンテナプラットフォームである Cloud Run サービスで、ビルドなしのソースコードからのデプロイ(Deploy from source without build)を試してみた結果をご紹介します。

Cloud Run サービスのデプロイ方法

Cloud Run サービスにおけるデプロイは、大きく分けて「コンテナイメージによるデプロイ」「ソースコードからのデプロイ」の2種類があります。このうち後者の「ソースコードからのデプロイ」は、さらに2種類に分けられます。

  1. ビルドありのソースからのデプロイ(Deploy from source with build)
  2. ビルドなしのソースからのデプロイ(Deploy from source without build)

上記のうち 1.は、ソースコードを指定するだけで、コマンドライン等から簡単に Cloud Run にデプロイできる手法です。デプロイにあたって Dockerfile の準備等は必要ありません。ソースコードの存在するディレクトリでコマンドライン等によりデプロイを実行すると、自動的に Cloud Build による Docker イメージのビルドが開始され、Cloud Run サービスにデプロイされます。

一方で 2. は、Cloud Build による Docker イメージのビルドをスキップします。ソースコードの存在するディレクトリでコマンドライン等によりデプロイを実行すると、アプリケーションのパッケージが Cloud Storage バケットにアップロードされます。Cloud Run では指定された各言語向けのベースイメージが実行され、その上でパッケージを取得して実行します。

当記事では、2. のビルドなしのソースからのデプロイを実際に試してみた結果をご紹介します。

制約事項

ビルドなしのソースからのデプロイでは、以下のような制約事項があります。

  • Cloud Run jobs では使用不可
  • 特定のランタイムしかサポートされない(Node.js、Python、Go、Java 等)
  • ソースアーカイブは圧縮後 250 MiB 以下
  • バイナリやスクリプトは x86 アーキテクチャ互換のみ
  • すべての依存関係がパッケージ化されている必要あり

その他の制約事項や最新情報は、以下の公式ドキュメントを参照してください。

前提条件

当記事の検証は、Google Cloud の Cloud Shell 上で行いました。

また、gcloud CLI のバージョンは以下のとおりです。

Google Cloud SDK 548.0.0

2025年11月21日現在(検証実施時)の Cloud Shell には、デフォルトで Google Cloud SDK 547.0.0 がインストールされており、このバージョンでは後に紹介する gcloud beta run deploy コマンドの --no-build オプションが実装されていませんでした。同バージョンでコマンドを実行しようとすると、以下のエラーが出力されます。

ERROR: (gcloud.beta.run.deploy) unrecognized arguments: –no-build

同オプションを使用するため、検証に先んじて gcloud コマンドをバージョンアップしました。

関連記事

Cloud Run の詳細については、以下の記事を参照してください。

blog.g-gen.co.jp

blog.g-gen.co.jp

アプリケーションの専用ディレクトリを作成し、以下のファイルを準備しました。

main.py
requirements.txt

main.py は、Cloud Storage オブジェクト gs://my-sample-bucket/sample.txt の情報を取得(describe)して標準出力に出力するシンプルなものです。ソースコードパッケージに Google Cloud クライアントライブラリを含めてデプロイするケースを検証したいため、このようなアプリケーションにしました。

main.py

import json
import os
import sys
    

sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'packages'))
   
from flask import Flask
from google.cloud import storage
  
app = Flask(__name__)
  
  
@app.route("https://blog.g-gen.co.jp/")
def describe_gcs_object():
    bucket_name = "my-sample-bucket"
    blob_name = "sample.txt"
  
    try:
        storage_client = storage.Client()
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.get_blob(blob_name)
  
        if blob is None:
            return f"Object {blob_name} not found in bucket {bucket_name}.", 404
  
        
        time_created_text = blob.time_created.strftime("%Y-%m-%d %H:%M:%S UTC")
        updated_text = blob.updated.strftime("%Y-%m-%d %H:%M:%S UTC")
  
        
        properties = {
            "message": "Object metadata has been printed to standard output.",
            "Bucket": blob.bucket.name,
            "Name": blob.name,
            "Content-Type": blob.content_type,
            "TimeCreated": time_created_text,
            "Updated": updated_text,
            "Size": blob.size,
            "Generation": blob.generation,
            "Metageneration": blob.metageneration,
            "Etag": blob.etag,
            "Crc32c": blob.crc32c,
            "ComponentCount": blob.component_count,
            "StorageClass": blob.storage_class,
        }
        message_json = json.dumps(properties)
        print(message_json)
  
        return "OK"
  
    except Exception as e:
        print(f"Error describing Cloud Storage object: {e}", file=sys.stderr)
        return "An error occurred.", 500
  
if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

requirements.txt

Flask==2.3.2
gunicorn==20.1.0
google-cloud-storage==2.7.0

ソースコードと同じディレクトリに、サブディレクトリ packages を作成しました(名称は任意)。

mkdir packages

その後、以下のコマンドを実行しました。

pip install -r requirements.txt -t packages

このコマンドにより、ディレクトリ packages に、必要な Python ライブラリが格納されます。

ソースコードと同じディレクトリで、以下のコマンドを実行します。

gcloud beta run deploy my-test-service \
  --project=my-project \
  --region=asia-northeast1 \
  --no-allow-unauthenticated \
  --source . \
  --no-build \
  --base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/python312 \
  --command=python \
  --args=main.py

およそ30秒後、デプロイが完了しました。以下のコマンドで動作確認をしたところ、オブジェクトの情報が Cloud Logging に出力され、期待どおりに動作することが確認できました。

curl -X GET "https://my-test-service-1234567890.asia-northeast1.run.app" \
-H "Authorization: bearer $(gcloud auth print-identity-token)" 

デプロイの所要時間

今回検証した「ビルドなしのソースからのデプロイ(Deploy from source without build)」のデプロイは、30秒〜35秒程度で完了しました。

もう1つの手法であるビルドありのソースからのデプロイ(Deploy from source with build)とのデプロイ所要時間を比較するため、同じソースコードとパッケージを、ビルドありの手法でデプロイしました。その結果、所要時間は2分00秒〜2分05秒程度でした。

起動時のパフォーマンス

「ビルドなしのソースからのデプロイ」では、各言語ランタイム向けのベースイメージを使用してコンテナを起動します。Cloud Run はコンテナが立ち上がった後にソースコードを取得・展開し、実行環境を整えます。

そのため、事前にソースコードをイメージ内にビルド(内包)しておく他の手法と比較すると、コンテナ起動時に「ソースコードの取得・展開」という処理が加わります。 これにより、特にコールドスタート時(初回アクセス時)において、リクエストからレスポンスが返るまでのレイテンシが増加する可能性があります。

ただし、このパフォーマンスへの影響について公式ドキュメントへの明記はなく、当記事でも高負荷なパッケージを用いた検証までは行えていません。あくまで仕様から推測される懸念点であるため、本番環境での採用を検討される際は、従来のデプロイ手法とパフォーマンスを比較検証することを推奨します。

杉村 勇馬 (記事一覧)

執行役員 CTO

元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。




元の記事を確認する

関連記事