App Engine Blobstore から Cloud Storage への移行(モジュール 16)

1. 概要

サーバーレス移行ステーション シリーズの Codelab(自分のペースで進められるハンズオン チュートリアル)と関連動画は、Google Cloud サーバーレス デベロッパーがアプリケーションをモダナイズできるよう、1 つ以上の移行(主にレガシー サービスからの移行)をガイドすることを目的としています。これにより、アプリのポータビリティが向上し、オプションと柔軟性が高まります。また、より幅広い Cloud プロダクトとの統合やアクセスが可能になり、新しい言語リリースへのアップグレードが容易になります。このシリーズは、当初は初期の Cloud ユーザー、主に App Engine(スタンダード環境)デベロッパーに焦点を当てていましたが、Cloud Functions や Cloud Run などの他のサーバーレス プラットフォームや、その他のプラットフォーム(該当する場合)も対象とするようになりました。

この Codelab では、App Engine Blobstore から Cloud Storage に移行する方法について説明します。また、以下からの暗黙的な移行もあります。

詳細な手順については、関連する移行モジュールをご覧ください。

GCP コンソールの

  • App Engine Blobstore API / ライブラリの使用を追加する
  • ユーザーのアップロードを Blobstore サービスに保存する
  • Cloud Storage への移行の次のステップを準備する

必要なもの

アンケート

このチュートリアルをどのように使用されますか?

通読のみ 通読して演習を行う

Python のご利用経験はどの程度ありますか?

初心者 中級者 上級者

Google Cloud サービスの使用経験はどの程度ありますか?

初心者 中級者 上級者

2. 背景情報

この Codelab では、モジュール 15 のサンプルアプリから始めて、Blobstore(および NDB)から Cloud Storage(および Cloud NDB)に移行する方法を説明します。移行プロセスでは、App Engine の以前のバンドル サービスへの依存関係を置き換えます。これにより、必要に応じてアプリを別の Cloud サーバーレス プラットフォームや他のホスティング プラットフォームに移行できます。

この移行には、このシリーズの他の移行よりも少し手間がかかります。Blobstore は元の webapp フレームワークに依存しているため、サンプルアプリでは Flask ではなく webapp2 フレームワークを使用しています。このチュートリアルでは、Cloud Storage、Cloud NDB、Flask、Python 3 への移行について説明します。

このアプリは、エンドユーザーの「訪問」を登録し、最新の 10 件を表示しますが、前回の Codelab(モジュール 15)では、Blobstore の使用に対応する新機能が追加されました。このアプリは、エンドユーザーに「訪問」に対応するアーティファクト(ファイル)をアップロードするよう求めます。ユーザーは、この操作を行うか、[スキップ] を選択してオプトアウトできます。ユーザーの決定にかかわらず、次のページには、このアプリの以前のバージョンと同じ出力がレンダリングされ、最新の訪問が表示されます。もう 1 つの工夫として、対応するアーティファクトがある訪問には、訪問のアーティファクトを表示するための「表示」リンクがあります。この Codelab では、前述の機能を維持しながら、前述の移行を実装します。

3. セットアップ / 事前準備

チュートリアルのメイン部分に入る前に、プロジェクトを設定し、コードを取得して、ベースライン アプリをデプロイしましょう。これにより、動作するコードから開始したことがわかります。

1. プロジェクトのセットアップ

モジュール 15 のアプリをすでにデプロイしている場合は、同じプロジェクト(およびコード)を再利用することをおすすめします。または、新しいプロジェクトを作成するか、別の既存のプロジェクトを再利用することもできます。プロジェクトに有効な請求先アカウントがあり、App Engine が有効になっていることを確認します。

2. ベースラインのサンプルアプリを入手する

この Codelab の前提条件の 1 つは、モジュール 15 のサンプルアプリが動作することです。お持ちでない場合は、モジュール 15 の「START」フォルダ(下記のリンク)から入手できます。この Codelab では、各ステップを順を追って説明し、モジュール 16 の「FINISH」フォルダの内容に似たコードを完成させます。

モジュール 15 の開始ファイルのディレクトリは次のようになります。

$ ls
README.md       app.yaml        main-gcs.py     main.py         templates

main-gcs.py ファイルは、モジュール 15 の main.py の代替バージョンです。これにより、プロジェクトの ID(PROJECT_ID.appspot.com)に基づいてアプリに割り当てられた URL のデフォルトとは異なる Cloud Storage バケットを選択できます。このファイルは、この(モジュール 16)Codelab では使用しません。ただし、必要に応じて、同様の移行手法をこのファイルに適用できます。

3. ベースライン アプリを(再)デプロイする

この段階で実施する必要がある残りの事前作業のステップ:

  1. gcloud コマンドライン ツールを学びなおす
  2. gcloud app deploy を使用してサンプルアプリを再デプロイする
  3. アプリが App Engine で問題なく動作することを確認する

これらの手順を正常に実行し、モジュール 15 のアプリが動作することを確認したら、最初のページには、アップロードする訪問アーティファクト ファイルを求めるフォームと、オプトアウトするための「スキップ」ボタンが表示されます。

f5b5f9f19d8ae978.png

ユーザーがファイルをアップロードするか、アップロードをスキップすると、アプリは、おなじみの「最近の訪問」ページを表示します。

f5ac6b98ee8a34cb.png

アーティファクトを含む訪問には、訪問タイムスタンプの右側に、アーティファクトを表示(またはダウンロード)するための [表示] リンクがあります。アプリの機能を確認したら、App Engine のレガシー サービス(webapp2、NDB、Blobstore)から最新の代替サービス(Flask、Cloud NDB、Cloud Storage)に移行する準備が整います。

4. 構成ファイルを更新する

更新版のアプリでは、3 つの構成ファイルが使用されます。必要なタスクは次のとおりです。

  1. app.yaml で必要な組み込みのサードパーティ ライブラリを更新し、Python 3 への移行を可能にする
  2. requirements.txt を追加して、組み込みでない必要なライブラリをすべて指定します。
  3. appengine_config.py を追加して、アプリが組み込みと非組み込みの両方のサードパーティ ライブラリをサポートするようにします。

app.yaml

libraries セクションを更新して app.yaml ファイルを編集します。jinja2 を削除し、grpcio、setuptools、ssl を追加します。3 つのライブラリすべてで利用可能な最新バージョンを選択します。また、Python 3 の runtime ディレクティブも追加しますが、コメントアウトします。完了すると、次のようになります(Python 3.9 を選択した場合)。

変更前:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

変更後:

#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

この変更は主に、App Engine サーバーで使用可能な Python 2 組み込みライブラリに関するものです(そのため、自分でバンドルする必要はありません)。Jinja2 は Flask に付属しているため削除しました。Flask は reqs.txt に追加します。Cloud NDB や Cloud Storage などの Google Cloud クライアント ライブラリを使用する場合は、grpcio と setuptools が必要です。最後に、Cloud Storage 自体に ssl ライブラリが必要です。上部にあるコメントアウトされたランタイム ディレクティブは、このアプリを Python 3 に移植する準備ができたときに使用します。このトピックについては、このチュートリアルの最後で説明します。

requirements.txt

requirements.txt ファイルを追加します。このファイルには、Flask フレームワーク、Cloud NDB クライアント ライブラリ、Cloud Storage クライアント ライブラリが必要です。これらは組み込みではありません。次の内容のファイルを作成します。

flask
google-cloud-ndb
google-cloud-storage

Python 2 App Engine ランタイムでは、組み込みでないサードパーティ ライブラリをセルフバンドルする必要があるため、次のコマンドを実行して、これらのライブラリを lib フォルダにインストールします。

pip install -t lib -r requirements.txt

開発マシンに Python 2 と 3 の両方がインストールされている場合は、pip2 コマンドを使用して、これらのライブラリの Python 2 バージョンを取得する必要があります。Python 3 にアップグレードすると、セルフバンドルは不要になります。

appengine_config.py

組み込みおよび組み込み以外のサードパーティ ライブラリをサポートする appengine_config.py ファイルを追加します。次の内容のファイルを作成します。

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

今完了した手順は、App Engine ドキュメントの Python 2 アプリ用のライブラリのインストールセクションに記載されている手順と類似しているか、同じであるはずです。具体的には、appengine_config.py の内容は、そのセクションのステップ 5 の内容と一致しているはずです。

構成ファイルに関する作業が完了したので、アプリケーションに進みましょう。

5. アプリケーション ファイルを変更する

インポート

main.py の最初の変更セットには、交換されるすべての部品の交換が含まれます。変更点は次のとおりです。

  1. webapp2 は Flask に置き換えられます。
  2. webapp2_extras の Jinja2 を使用する代わりに、Flask に付属の Jinja2 を使用します。
  3. App Engine Blobstore と NDB は Cloud NDB と Cloud Storage に置き換えられます。
  4. webapp の Blobstore ハンドラは、io 標準ライブラリ モジュール、Flask、werkzeug ユーティリティの組み合わせに置き換えられます。
  5. デフォルトでは、Blobstore はアプリの URL(PROJECT_ID.appspot.com)に合わせて名前を付けた Cloud Storage バケットに書き込みます。Cloud Storage クライアント ライブラリに移植するため、google.auth を使用してプロジェクト ID を取得し、まったく同じバケット名を指定します。(バケット名はハードコードされていないため、変更できます)。

変更前:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

main.py の現在のインポート セクションを次のコード スニペットに置き換えて、上記のリストの変更を実装します。

変更後:

import io

from flask import (Flask, abort, redirect, render_template,
        request, send_file, url_for)
from werkzeug.utils import secure_filename

import google.auth
from google.cloud import exceptions, ndb, storage

初期化と不要な Jinja2 のサポート

次に置き換えるコードブロックは、webapp2_extras から Jinja2 の使用を指定する BaseHandler です。Jinja2 は Flask に付属しており、デフォルトのテンプレート エンジンであるため、これは不要です。削除してください。

モジュール 16 側では、以前のアプリにはなかったオブジェクトをインスタンス化します。これには、Flask アプリの初期化、Cloud NDB と Cloud Storage の API クライアントの作成が含まれます。最後に、インポート セクションで説明したように、Cloud Storage バケット名をまとめます。これらの更新を実装する前と後の違いは次のとおりです。

変更前:

class BaseHandler(webapp2.RequestHandler):
    'Derived request handler mixing-in Jinja2 support'
    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        self.response.write(self.jinja2.render_template(_template, **context))

変更後:

app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID

Datastore へのアクセスを更新する

Cloud NDB は App Engine NDB とほぼ互換性があります。すでに説明した違いの 1 つは、API クライアントが必要であることです。もう 1 つは、後者では Datastore へのアクセスを API クライアントの Python コンテキスト マネージャーで制御する必要があることです。基本的に、これは、Cloud NDB クライアント ライブラリを使用するすべての Datastore アクセス呼び出しが Python with ブロック内でのみ発生することを意味します。

これが 1 つ目の変更です。もう 1 つの変更は、Blobstore とそのオブジェクト(BlobKey など)が Cloud Storage でサポートされていないため、file_blob を ndb.StringProperty に変更することです。以下は、データモデル クラスと、これらの変更を反映した更新済みの store_visit() 関数と fetch_visits() 関数です。

変更前:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent),
            file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

変更後:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.StringProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

これまでに加えられた変更を、図で表すと次のようになります。

a8f74ca392275822.png

ハンドラの更新

アップロード ハンドラ

webapp2 のハンドラはクラスですが、Flask では関数です。Flask では、HTTP 動詞メソッドではなく、動詞を使用して関数を装飾します。Blobstore とその webapp ハンドラは、Cloud Storage の機能、Flask とそのユーティリティに置き換えられます。

変更前:

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    'Upload blob (POST) handler'
    def post(self):
        uploads = self.get_uploads()
        blob_id = uploads[0].key() if uploads else None
        store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
        self.redirect('/', code=307)

変更後:

@app.route('/upload', methods=['POST'])
def upload():
    'Upload blob (POST) handler'
    fname = None
    upload = request.files.get('file', None)
    if upload:
        fname = secure_filename(upload.filename)
        blob = gcs_client.bucket(BUCKET).blob(fname)
        blob.upload_from_file(upload, content_type=upload.content_type)
    store_visit(request.remote_addr, request.user_agent, fname)
    return redirect(url_for('root'), code=307)

この更新に関する注意事項は次のとおりです。

  • blob_id ではなく、ファイル アーティファクトは、ファイル名(fname)が存在する場合はファイル名で識別され、存在しない場合は None で識別されるようになりました(ユーザーがファイルのアップロードをオプトアウトした場合)。
  • Blobstore ハンドラはアップロード プロセスをユーザーから抽象化していましたが、Cloud Storage はそうではないため、ファイルの blob オブジェクトと場所(バケット)を設定する新しく追加されたコードと、実際のアップロードを実行する呼び出しを確認できます。(upload_from_file())を更新します。
  • webapp2 では、アプリケーション ファイルの下部にあるルーティング テーブルを使用しますが、Flask のルートは、デコレートされた各ハンドラにあります。
  • どちらのハンドラも、HTTP 307 戻りコードで POST リクエストを保持しながら、ホーム(/)にリダイレクトすることで機能を終了します。

ダウンロード ハンドラ

ダウンロード ハンドラの更新は、アップロード ハンドラと同様のパターンに従いますが、確認するコードははるかに少なくなります。Blobstore と webapp の機能を、Cloud Storage と Flask の同等の機能に置き換えます。

変更前:

class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
    'view uploaded blob (GET) handler'
    def get(self, blob_key):
        self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)

変更後:

@app.route('/view/<path:fname>')
def view(fname):
    'view uploaded blob (GET) handler'
    blob = gcs_client.bucket(BUCKET).blob(fname)
    try:
        media = blob.download_as_bytes()
    except exceptions.NotFound:
        abort(404)
    return send_file(io.BytesIO(media), mimetype=blob.content_type)

このアップデートに関する注意事項:

  • ここでも、Flask はハンドラ関数をルートで装飾しますが、webapp は下部のルーティング テーブルで装飾します。後者のパターン マッチング構文 ('/view/([^/]+)?')と Flask の構文('/view/<path:fname>')を認識してください。
  • アップロード ハンドラと同様に、Blobstore ハンドラによって抽象化された機能(問題のファイル(blob)を識別し、バイナリを明示的にダウンロードする機能)については、Cloud Storage 側で少し追加の作業が必要です。Blobstore ハンドラでは、単一の send_blob() メソッド呼び出しで済みます。
  • どちらの場合も、アーティファクトが見つからない場合は HTTP 404 エラーがユーザーに返されます。

メインハンドラ

メイン ハンドラで、メイン アプリケーションに最終的な変更を加えます。webapp2 HTTP 動詞メソッドは、それらの機能を組み合わせた単一の関数に置き換えられます。MainHandler クラスを root() 関数に置き換え、次のように webapp2 ルーティング テーブルを削除します。

変更前:

class MainHandler(BaseHandler):
    'main application (GET/POST) handler'
    def get(self):
        self.render_response('index.html',
                upload_url=blobstore.create_upload_url('/upload'))

    def post(self):
        visits = fetch_visits(10)
        self.render_response('index.html', visits=visits)

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/upload', UploadHandler),
    ('/view/([^/]+)?', ViewBlobHandler),
], debug=True)

変更後:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

get() メソッドと post() メソッドを別々に使用するのではなく、root() の if-else ステートメントを使用します。また、root() は単一の関数であるため、GET と POST の両方のテンプレートをレンダリングするための呼び出しは 1 つだけです。一方、webapp2 ではこれは不可能です。

main.py に対する 2 回目(最後)の変更を視覚的に表した図を以下に示します。

5ec38818c32fec2.png

(省略可)下位互換性の「強化」

そのため、上記で作成したソリューションは完全に機能しますが、これはゼロから開始し、Blobstore で作成されたファイルがない場合に限られます。BlobKey ではなくファイル名でファイルを識別するようにアプリを更新したため、完成したモジュール 16 のアプリは、そのままでは Blobstore ファイルを表示できません。つまり、この移行では下位互換性のない変更を行いました。このギャップを埋めるために、main.py の代替バージョンである main-migrate.py(リポジトリにあります)を導入しました。

Blobstore で作成されたファイルをサポートする最初の「拡張機能」は、BlobKeyProperty を持つデータモデルです(Cloud Storage で作成されたファイルの StringProperty に加えて)。

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()  # backwards-compatibility
    file_gcs  = ndb.StringProperty()

file_blob プロパティは Blobstore によって作成されたファイルを識別するために使用され、file_gcs は Cloud Storage ファイルに使用されます。新しい来店を作成するときに、file_blob ではなく file_gcs に値を明示的に保存します。これにより、store_visit は少し異なるものになります。

変更前:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

変更後:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_gcs=upload_key).put()

最新の訪問を取得するときに、データを「正規化」してからテンプレートに送信します。

変更前:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

変更後:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = etl_visits(fetch_visits(10))
    return render_template('index.html', **context)

次に、file_blob または file_gcs のいずれか(またはどちらでもない)が存在することを確認します。使用可能なファイルがある場合は、存在するファイルを選択し、その識別子(Blobstore で作成されたファイルの場合は BlobKey、Cloud Storage で作成されたファイルの場合はファイル名)を使用します。「Cloud Storage で作成されたファイル」とは、Cloud Storage クライアント ライブラリを使用して作成されたファイルを指します。Blobstore も Cloud Storage に書き込みますが、この場合は Blobstore で作成されたファイルになります。

さらに重要なのは、エンドユーザー向けにデータを正規化または ETL(抽出、変換、読み込み)するために使用される etl_visits() 関数とは何かということです。たとえば、次のようになります。

def etl_visits(visits):
    return [{
            'visitor': v.visitor,
            'timestamp': v.timestamp,
            'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
                    and v.file_gcs else v.file_blob
            } for v in visits]

おそらく、想定どおりの処理が行われています。コードはすべてのアクセスをループし、アクセスごとに訪問者とタイムスタンプのデータをそのまま取得して、file_gcs または file_blob が存在するかどうかを確認し、存在する場合はそのいずれかを選択します(どちらも存在しない場合は None)。

main.py と main-migrate.py の違いを次の図に示します。

718b05b2adadb2e1.png

Blobstore で作成されたファイルがない状態で最初から始める場合は、main.py を使用します。ただし、移行中で、Blobstore と Cloud Storage の両方で作成されたファイルをサポートする場合は、main-migrate.py を参照して、このようなシナリオに対処する方法の例を確認し、独自のアプリの移行を計画してください。複雑な移行を行う場合、特殊なケースが発生する可能性が高いため、この例は、実際のデータを使用して実際のアプリをモダナイズする際の親和性を高めることを目的としています。

6. まとめ / クリーンアップ

このセクションでは、アプリをデプロイし、想定どおりに動作することと、出力に反映されることを確認して、この Codelab を終了します。アプリの検証後、クリーンアップ手順を実行し、次のステップを検討します。

アプリケーションをデプロイして検証する

アプリを再デプロイする前に、必ず pip install -t lib -r requirements.txt を実行して、自己バンドルされたサードパーティ ライブラリを lib フォルダに取得してください。下位互換性のあるソリューションを実行する場合は、まず main-migrate.py の名前を main.py に変更します。gcloud app deploy を実行し、アプリがモジュール 15 のアプリと同じように動作することを確認します。フォーム画面は次のようになります。

f5b5f9f19d8ae978.png

[最近の訪問] ページは次のようになります。

f5ac6b98ee8a34cb.png

この Codelab を完了し、App Engine Blobstore を Cloud Storage に、App Engine NDB を Cloud NDB に、webapp2 を Flask に置き換えることができました。コードは、FINISH(モジュール 16)フォルダの内容と一致しているはずです。代替の main-migrate.py もそのフォルダにあります。

Python 3 への「移行」

app.yaml の先頭にあるコメントアウトされた Python 3 runtime ディレクティブは、このアプリを Python 3 に移植するために必要なものです。ソースコード自体はすでに Python 3 と互換性があるため、変更は必要ありません。これを Python 3 アプリとしてデプロイするには、次の手順を行います。

  1. app.yaml の上部にある Python 3 runtime ディレクティブのコメント化を解除します。
  2. app.yaml 内の他の行をすべて削除します。
  3. ファイル appengine_config.py を削除します。(Python 3 ランタイムでは未使用)
  4. lib フォルダが存在する場合は削除します。(Python 3 ランタイムでは不要)

クリーンアップ

全般

現時点で作業が完了している場合は、課金が発生しないように App Engine アプリを無効にすることをおすすめします。ただし、さらにテストや試験運用を行う場合は、App Engine プラットフォームに無料の割り当てがあるため、その使用量の上限を超えない限り、課金されることはありません。これはコンピューティングに関するものですが、関連する App Engine サービスにも料金が発生する場合があります。詳細については、料金ページをご覧ください。この移行に他の Cloud サービスが含まれる場合、それらのサービスは個別に課金されます。どちらの場合も、該当する場合は、後述の「この Codelab に固有」セクションをご覧ください。

App Engine などの Google Cloud サーバーレス コンピューティング プラットフォームにデプロイすると、わずかなビルド費用とストレージ費用が発生します。Cloud Build には、Cloud Storage と同様に独自の無料割り当てがあります。そのイメージのストレージは、この割り当ての一部を使用します。ただし、このような無料枠がない地域にお住まいの場合は、ストレージ使用量に注意して、潜在的な費用を最小限に抑えてください。確認する必要がある特定の Cloud Storage の「フォルダ」には、次のものがあります。

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • 上記のストレージ リンクは、PROJECT_ID と *LOC*ation によって異なります。たとえば、アプリが米国でホストされている場合は「us」になります。

一方、このアプリケーションや他の関連する移行 Codelab を続行せず、すべてを完全に削除する場合は、プロジェクトをシャットダウンします。

この Codelab に固有

以下のサービスは、この Codelab に固有のものです。詳細については、各プロダクトのドキュメントをご覧ください。

モジュール 15 から 16 に移行した場合でも、Blobstore にデータが残っているため、上記の料金情報に Blobstore が含まれています。

次のステップ

このチュートリアル以外にも、以前のバンドル サービスからの移行に焦点を当てた移行モジュールがあります。

App Engine は、Google Cloud で唯一のサーバーレス プラットフォームではなくなりました。小規模な App Engine アプリや機能が制限されたアプリをスタンドアロンのマイクロサービスに変換する場合や、モノリシック アプリを複数の再利用可能なコンポーネントに分割する場合は、Cloud Functions への移行を検討することをおすすめします。コンテナ化がアプリケーション開発ワークフローの一部になっている場合、特に CI / CD(継続的インテグレーション / 継続的デリバリーまたはデプロイ)パイプラインで構成されている場合は、Cloud Run への移行を検討してください。これらのシナリオは、次のモジュールで取り上げます。

  • App Engine から Cloud Functions に移行する: モジュール 11 をご覧ください。
  • App Engine から Cloud Run に移行する: Docker を使用してアプリをコンテナ化するにはモジュール 4 を、コンテナ、Docker の知識、Dockerfile なしで移行するにはモジュール 5 をご覧ください。

別のサーバーレス プラットフォームへの切り替えは任意です。変更を行う前に、アプリとユースケースに最適なオプションを検討することをおすすめします。

次に検討する移行モジュールに関係なく、すべてのサーバーレス移行ステーションのコンテンツ(Codelab、動画、ソースコード [利用可能な場合])には、オープンソース リポジトリからアクセスできます。リポジトリの README には、検討すべき移行と、移行モジュールの関連する「順序」に関するガイダンスも記載されています。

7. 参考情報

Codelab に関する問題 / フィードバック

この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:

移行に関するリソース

モジュール 15(開始)とモジュール 16(終了)のリポジトリ フォルダへのリンクを以下の表に示します。また、すべての App Engine Codelab 移行用のリポジトリからアクセスすることもできます。このリポジトリは、クローンを作成するか、ZIP ファイルをダウンロードできます。

Codelab

Python 2

Python 3

モジュール 15

コード

なし

モジュール 16(この Codelab)

コード

(Python 2 と同じ)

オンライン リソース

このチュートリアルに関連するオンライン リソースは次のとおりです。

App Engine Blobstore と Cloud Storage

App Engine プラットフォーム

その他のクラウド情報

Python

動画

ライセンス

この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。