Google Cloud Runでコンテナアプリをデプロイ

Google Cloud Runを使えば、サーバーを管理せずにコンテナを実行できます。Dockerイメージをデプロイするだけで、Cloud Runがスケーリング、HTTPS、インフラを自動的に処理します。このチュートリアルでは、Python Flask REST APIを構築し、コンテナ化してCloud Runにデプロイします。

前提条件

  • 課金が有効なGoogle Cloudアカウント
  • gcloud CLIのインストールと認証
  • ローカルにDockerをインストール
  • Python 3.11+
  • ステップ1:Flaskアプリケーションの作成

    プロジェクトディレクトリを作成し、アプリケーションをセットアップ:

    mkdir cloud-run-demo && cd cloud-run-demo
    

    python -m venv venv && source venv/bin/activate

    pip install flask gunicorn google-cloud-firestore

    app.pyを作成:

    import os
    

    from flask import Flask, jsonify, request

    from google.cloud import firestore

    app = Flask(__name__)

    db = firestore.Client()

    @app.route('/health')

    def health():

    return jsonify({'status': 'healthy', 'service': 'cloud-run-demo'})

    @app.route('/api/items', methods=['GET'])

    def list_items():

    items_ref = db.collection('items')

    docs = items_ref.stream()

    items = [{'id': doc.id, **doc.to_dict()} for doc in docs]

    return jsonify({'items': items, 'count': len(items)})

    @app.route('/api/items', methods=['POST'])

    def create_item():

    data = request.get_json()

    if not data or 'name' not in data:

    return jsonify({'error': 'name is required'}), 400

    item = {

    'name': data['name'],

    'description': data.get('description', ''),

    'created_at': firestore.SERVER_TIMESTAMP

    }

    doc_ref = db.collection('items').add(item)

    return jsonify({'id': doc_ref[1].id, 'message': 'created'}), 201

    @app.route('/api/items/<item_id>', methods=['DELETE'])

    def delete_item(item_id):

    db.collection('items').document(item_id).delete()

    return jsonify({'message': 'deleted'}), 200

    if __name__ == '__main__':

    port = int(os.environ.get('PORT', 8080))

    app.run(host='0.0.0.0', port=port, debug=False)

    requirements.txtを作成:

    flask==3.0.0
    

    gunicorn==21.2.0

    google-cloud-firestore==2.14.0

    ステップ2:Dockerfileの作成

    マルチステージDockerfileで軽量な本番イメージを作成:

    # ビルドステージ
    

    FROM python:3.11-slim AS builder

    WORKDIR /app

    COPY requirements.txt .

    RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

    # 本番ステージ

    FROM python:3.11-slim

    WORKDIR /app

    COPY --from=builder /install /usr/local

    COPY . .

    ENV PORT=8080

    EXPOSE 8080

    CMD exec gunicorn --bind :$PORT --workers 2 --threads 4 --timeout 120 app:app

    ステップ3:ローカルでテスト

    docker build -t cloud-run-demo .
    

    docker run -p 8080:8080 -e PORT=8080 cloud-run-demo

    curl http://localhost:8080/health

    ステップ4:Google Cloud Runへデプロイ

    export PROJECT_ID=your-project-id
    

    gcloud config set project $PROJECT_ID

    # 必要なAPIを有効化

    gcloud services enable run.googleapis.com \

    containerregistry.googleapis.com \

    cloudbuild.googleapis.com \

    firestore.googleapis.com

    # Cloud Buildでビルド&プッシュ

    gcloud builds submit --tag gcr.io/$PROJECT_ID/cloud-run-demo

    # Cloud Runにデプロイ

    gcloud run deploy cloud-run-demo \

    --image gcr.io/$PROJECT_ID/cloud-run-demo \

    --platform managed \

    --region asia-northeast1 \

    --allow-unauthenticated \

    --memory 256Mi \

    --cpu 1 \

    --min-instances 0 \

    --max-instances 10

    ステップ5:オートスケーリングの設定

    gcloud run services update cloud-run-demo \
    

    --region asia-northeast1 \

    --concurrency 80 \

    --min-instances 1 \

    --max-instances 50

    主要なスケーリングパラメータ:

  • concurrency: インスタンスあたりの最大リクエスト数(デフォルト80)
  • min-instances: 最小ウォームインスタンス数(デフォルト0)
  • max-instances: 最大インスタンス数(デフォルト100)

ステップ6:カスタムドメインの設定

gcloud run domain-mappings create \

--service cloud-run-demo \

--domain api.yourdomain.com \

--region asia-northeast1

ステップ7:Cloud BuildによるCI/CD

cloudbuild.yamlを作成:

steps:

- name: 'gcr.io/cloud-builders/docker'

args: ['build', '-t', 'gcr.io/$PROJECT_ID/cloud-run-demo:$COMMIT_SHA', '.']

- name: 'gcr.io/cloud-builders/docker'

args: ['push', 'gcr.io/$PROJECT_ID/cloud-run-demo:$COMMIT_SHA']

- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'

entrypoint: gcloud

args: ['run', 'deploy', 'cloud-run-demo', '--image', 'gcr.io/$PROJECT_ID/cloud-run-demo:$COMMIT_SHA', '--region', 'asia-northeast1', '--platform', 'managed']

ステップ8:モニタリングとログ

gcloud logging read "resource.type=cloud_run_revision \

AND resource.labels.service_name=cloud-run-demo" \

--limit 50 --format json

構造化ログの追加:

import json, sys

def log(severity, message, **kwargs):

entry = {'severity': severity, 'message': message, **kwargs}

print(json.dumps(entry), file=sys.stdout if severity != 'ERROR' else sys.stderr)

コスト最適化のヒント

1. 開発環境ではmin-instancesを0に設定

2. CPUスロットリングでアイドル時のコストを削減

3. メモリは256Miから始めて必要に応じて増加

4. --cpu-boostでコールドスタートを高速化

5. concurrencyを高く設定(80-100)してインスタンスあたりのリクエストを最大化

まとめ

Google Cloud Runは、サーバーレス関数と本格的なKubernetesの中間に位置する強力なプラットフォームです。コンテナの柔軟性とサーバーレスのシンプルさを兼ね備え、クラスター管理不要、自動HTTPS、従量課金で利用できます。API、マイクロサービス、効率的にスケールが必要なWebアプリケーションに最適です。