Python ランタイム

Python ランタイムは、アプリケーションのコードと依存関係をインストールして、フレキシブル環境でそのアプリケーションを実行する役割を果たすソフトウェア スタックです。

Python のバージョン

Python 3.12 は Buildpack を使用します。サポートされている Python のバージョンと、それに対応する Ubuntu のバージョンの完全なリストについては、ランタイム サポート スケジュールをご覧ください。

サポート対象の Python バージョンを使用するには、次のことを行う必要があります。

  • app.yaml ファイルに runtime_configoperating_system の設定を追加して、オペレーティング システムを指定します。

  • gcloud CLI バージョン 420.0.0 以降をインストールします。CLI ツールを更新するには、gcloud components update コマンドを実行します。インストールされているバージョンを表示するには、gcloud version コマンドを実行します。

  • 必要に応じて、app.yaml ファイルに runtime_version 設定を含めると、ランタイム バージョンを指定できます。runtime_version の設定が指定されていない場合は、デフォルトで最新の Python バージョンが使用されます。

  • Ubuntu 22 で Python 3.12 を指定するには、次のようにします。

    runtime: python
    env: flex
    entrypoint: gunicorn -b :$PORT main:app
    
    runtime_config:
        operating_system: "ubuntu22"
        runtime_version: "3.12"
    
  • Ubuntu 22 でサポートされている最新の Python バージョンを指定するには、次のようにします。

      runtime: python
      env: flex
      entrypoint: gunicorn -b :$PORT main:app
    
      runtime_config:
          operating_system: "ubuntu22"
    

詳細については、app.yaml リファレンス ページをご覧ください。

以前のランタイム バージョン

Python バージョン 3.7 以前の場合は、アプリケーションの app.yaml ファイルで runtime_configpython_version の設定を使用してバージョンを指定します。

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
    python_version: 3.7

Python バージョン 3.7 以前では、runtime_config または python_version が省略されている場合、デフォルトのインタープリタは Python 2.7.12 です。たとえば、app.yaml ファイルで runtime: python を指定すると、デフォルトのランタイムを使用できます。

runtime: python
env: flex

詳細については、app.yaml リファレンス ページをご覧ください。

次の表では、バージョン設定ごとにデプロイされるインタープリタを示します。

python_version 設定 デプロイされるインタープリタ ランタイム ID app.yaml の例
2(デフォルト) 2.7.12 python2 runtime_config:
python_version: 2
3.4 3.4.8 python34 runtime_config:
python_version: 3.4
3.5 3.5.9 python35 runtime_config:
python_version: 3.5
3 または 3.6 3.6.10 python36 runtime_config:
python_version: 3
3.7 3.7.9 python37 runtime_config:
python_version: 3.7

他の Python ランタイムのサポート

サポート対象外の Python バージョンを使用する必要がある場合は、カスタム ランタイムを作成し、必要な Python バージョンを含む有効なベースイメージを選択します。

Google 提供のベースイメージまたは Docker Python ベースイメージについては、カスタム ランタイムのビルドをご覧ください。

Cloud Run 用 App Engine アプリのコンテナ化の詳細については、移行ガイドをご覧ください。

依存関係

ランタイムは、アプリケーションの起動前にアプリケーションのソース ディレクトリで requirements.txt ファイルを探し、pip を使用して依存関係をインストールします。パッケージの宣言と管理については、Python ライブラリの使用をご覧ください。

アプリでプライベート依存関係が必要な場合は、Python ランタイムに基づくカスタム ランタイムを使用して適切なパッケージをインストールする必要があります。

アプリケーションの起動

ランタイムは、app.yaml ファイルで定義された entrypoint を使用してアプリを起動します。エントリ ポイントは、環境変数 PORT で定義されたポートで HTTP リクエストのレスポンス処理を開始する必要があります。

ほとんどのウェブ アプリケーションは、GunicornuWSGIWaitress などの WSGI サーバーを使用します。

これらのサーバーのいずれかを使用するには、アプリケーションの requirements.txt にそれらを依存関係として追加する必要があります。 Flask アプリケーションに gunicorn を使用する場合は、アプリケーションの Python バージョンに gunicorn との互換性があることを確認してください。

ランタイムは、エントリ ポイントが呼び出される前に、すべての依存関係がインストールされていることを確認します。

Flask==2.0.2
gunicorn==20.1.0

Flask アプリケーションで gunicorn を使用したエントリ ポイントの例:

entrypoint: gunicorn -b :$PORT main:app

Django アプリケーションで gunicorn を使用したエントリ ポイントの例:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

Gunicorn はおすすめの WSGI サーバーですが、他の WSGI サーバーを使用することもできます。たとえば、Flask で uWSGI を使用するエントリ ポイントの例を示します。

entrypoint: uwsgi --http :$PORT --wsgi-file main.py --callable app

WSGI サーバーなしでリクエストを処理できるアプリケーションの場合には、Python スクリプトを実行します。

entrypoint: python main.py

上のエントリ ポイントの例は基本的なものにすぎませんが、お使いのウェブ アプリケーションが機能する可能性はあります。ただし、ほとんどのアプリケーションでは WSGI サーバーの構成がさらに必要となります。エントリポイントのすべての設定を指定する代わりに、app.yaml ファイルがあるプロジェクトのルート ディレクトリに gunicorn.conf.py ファイルを作成し、エントリポイントで指定します。

entrypoint: gunicorn -c gunicorn.conf.py -b :$PORT main:app

Gunicorn の構成値の詳細については、Gunicorn のドキュメントをご覧ください。

ワーカー

Gunicorn は、リクエストの処理にワーカーを使用します。デフォルトでは、Gunicorn はシンクワーカーを使用します。このワーカークラスはすべてのウェブ アプリケーションと互換性がありますが、各ワーカーは一度に 1 つのリクエストしか処理できません。デフォルトでは、gunicorn はこれらのワーカーの 1 つを使用します。このため、インスタンスが十分に活用されず、負荷の高いアプリケーションではレイテンシが長くなることが少なくありません。

インスタンスの CPU コア数を 2~4 倍して 1 を加えた数に設定することをおすすめします。これは gunicorn.conf.py で次のとおりに指定できます。

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1

さらに、ほとんどの I/O がバインドされているウェブ アプリケーションの中には、別のワーカークラスを使用することでパフォーマンスが向上するものもあります。ワーカークラスが gevent や tornado などの依存関係を必要とする場合、これらの依存関係をアプリケーションの requirements.txt で宣言する必要があります。

HTTPS プロキシと転送プロキシ

App Engine はロードバランサで HTTPS 接続を終了し、リクエストをアプリケーションに転送します。ほとんどのアプリケーションでは、リクエストが HTTPS 上で送信されたかどうかを知る必要はありませんが、この情報が必要なアプリケーションでは、gunicorn.conf.py で App Engine プロキシを信頼するように Gunicorn を構成する必要があります。

forwarded_allow_ips = '*'
secure_scheme_headers = {'X-FORWARDED-PROTO': 'https'}

Gunicorn は、ほとんどのウェブ フレームワークがリクエストの指標として使用する 'https' への wsgi.url_scheme が安全であることをすぐ確認します。WSGI サーバーまたはフレームワークがこれをサポートしていない場合は、X-Forwarded-Proto ヘッダーの値を手動で確認するだけです。

一部のアプリケーションでは、ユーザーの IP アドレスの確認が必要になります。これは X-Forwarded-For ヘッダーで確認できます。

gunicorn.conf.pysecure_scheme_headers 設定は X-FORWARDED-PROTO のように大文字にする必要がありますが、コードが読むことができるヘッダーは X-Forwarded-Proto のように大文字と小文字を混在できます。

ランタイムの拡張

フレキシブル環境の Python ランタイムを使用して、カスタム ランタイムを作成できます。詳細については、Python のカスタマイズをご覧ください。

環境変数

次の環境変数が、ランタイム環境によって設定されます。

環境変数 説明
GAE_INSTANCE 現在のインスタンスの名前。
GAE_MEMORY_MB アプリケーション プロセスで使用可能なメモリ量。
GAE_SERVICE アプリケーションの app.yaml ファイルで指定されたサービス名。サービス名が指定されていない場合は、default に設定されます。
GAE_VERSION 現在のアプリケーションのバージョン ラベル。
GOOGLE_CLOUD_PROJECT アプリケーションに関連付けられたプロジェクト ID。この ID は、Google Cloud コンソールに表示されます。
PORT HTTP リクエストを受信するポート。

app.yaml ファイルで追加の環境変数を設定できます。

メタデータ サーバー

アプリケーションのインスタンスは、ホスト名、外部 IP アドレス、インスタンス ID、カスタム メタデータ、サービス アカウント情報など、インスタンスに関する情報を Compute Engine メタデータ サーバーから取得します。App Engine では、インスタンスごとにカスタム メタデータを設定することはできませんが、プロジェクト単位のカスタム メタデータを設定して、App Engine インスタンスや Compute Engine インスタンスから読み取ることができます。

次のサンプル関数では、メタデータ サーバーからインスタンスの外部 IP アドレスを取得します。

METADATA_NETWORK_INTERFACE_URL = (
    "http://metadata/computeMetadata/v1/instance/network-interfaces/0/"
    "access-configs/0/external-ip"
)


def get_external_ip():
    """Gets the instance's external IP address from the Compute Engine metadata
    server.

    If the metadata server is unavailable, it assumes that the application is running locally.

    Returns:
        The instance's external IP address, or the string 'localhost' if the IP address
        is not available.
    """
    try:
        r = requests.get(
            METADATA_NETWORK_INTERFACE_URL,
            headers={"Metadata-Flavor": "Google"},
            timeout=2,
        )
        return r.text
    except requests.RequestException:
        logging.info("Metadata server could not be reached, assuming local.")
        return "localhost"