Google App Engine StandardでPython3.7、Flask1.0を動かす

2018年12月20日に、Google App EngineでPython3.7が正式版(generally available)としてリリースされた🎉

この記事ではGoogle App Engineのローカル環境での動かし方、そしてデプロイの方法を記載する。

Macでローカル環境のFlaskが動くようにする

こちらにMacにpyenvとpipenvを使ってPythonが動く環境を構築する方法を記載している。

pipenvでFlaskをインストールし、templatesディレクトリ下に静的ファイルを確認するためのindex.htmlを用意する(中身はなんでもよい)。

ディレクトリ

.
├── Pipfile
├── Pipfile.lock
├── main.py
└── templates
    └── index.html

main.pyでFlaskを初期化し、/アクセス時にHTMLを表示し、/api/dummyアクセス時にJSONが返せるようにする。
HTMLはrender_template関数でファイル名を指定している。JSONはapp.config['JSON_AS_ASCII'] = Falseで文字化けしないようにし、jsonify関数でJSONを返している。

main.py

from flask import Flask, render_template, jsonify

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/api/dummy')
def dummy():
    return jsonify({
        "key": "値"
    })


if __name__ == '__main__':
    app.run()

python main.pyでアプリケーションサーバーが起動し、/でHTML、/api/dummyがJSON返されればOK。

python main.py

ローカル環境でGunicornを使いFlaskを動かす

Google App Engine standardのローカル環境での開発は、Python2.7ではdev_appserver.pyを使う方法が公式で紹介されていたが、Python3.7ではdev_appserver.pyの使用は非推奨だ。

We do not recommend that you depend on tools like dev_appserver, the local development server provided with the Google Cloud SDK.
https://cloud.google.com/appengine/docs/standard/python3/testing-and-deploying-your-app

代わりに、WSGI(Web Server Gateway Interface)サーバである(Gunicorn)[https://gunicorn.org/]を使う方法が紹介されている。

Gunicornを使いFlaskを動かせるようにしていく。
まずはGunicornをインストールする。

pipenv install gunicorn==19.9.0

gunicornコマンドは次の引数を受け取りサーバーを立ち上げる。

gunicorn [OPTIONS] APP_MODULE

APP_MODULE$(MODULE_NAME):$(VARIABLE_NAME)を指定する。
$(MODULE_NAME)にはFlaskを初期化しているモジュール名(main)を指定する。
$(VARIABLE_NAME)にはFlaskインスタンス名(app)を指定する。

-bオプションはHOSTHOST:PORTunix:PATHのいずれかを指定できる。
HOSTにはIPを指定可能だ。

次のように起動することで127.0.0.1:8000にアクセスするとFlaskのウェブアプリケーションにアクセスできる。

gunicorn -b 127.0.0.1:8000 main:app

HTML、JSONが想定通り返ってきている。
gunicornで起動してHTMLの表示を確認

gunicornで起動してJSONを確認

なお、dev_appserver.pyを使わないとapp.yamlの内容が確認できないため、dev_appserver.pyを使ってPython3.7を動かす方法を別記事にしている。

Google App EngineにFlaskをデプロイする

次の手順で、ローカルで挙動を確認できたWebアプリケーションをデプロイする。

  1. Google App Engineにデプロイするために必要なファイルを作成する。
    1. app.yamlを作成する。
    2. Pipfileからrequirements.txtを生成する。(pipenvを使っている場合)
    3. デプロイ不要なファイルを.gcloudignoreに指定する。
  2. Cloud SDKをインストールする。
  3. プロジェクトを作成する。
  4. Google App Engineを有効にする。
  5. 課金を有効にする。
  6. デプロイする。
  7. プロジェクトを削除する。(お試しでプロジェクトを作成していた場合)

Google App Engineにデプロイするために必要なファイルを作成する

Pythonのバージョンやオートスケールの設定、静的ファイルの扱いなどを指定するapp.yaml、依存関係を解決するrequirements.txt、デデプロイから除外するフィアルを指定する.gcloudignoreを作成する。

app.yamlを作成する

最低限pythonのバージョン3.7を使うこと、そしてgunicornを使うことをapp.yamlに記載する。 $PORTは実行時に設定される環境変数で、HTTP リクエストを受信するポートだ。
その他の環境変数は、こちらで確認できる。

app.yaml

runtime: python37
entrypoint: gunicorn -b :$PORT main:app

requirements.txtを作成する

PipfileおよびPipfile.lockは2019/5/12時点ではサポートされていない。

Dependency specification using the Pipfile/Pipfile.lock standard is currently not supported and your project must not have these files present.
https://cloud.google.com/appengine/docs/standard/python3/runtime

なので、次のコマンドでPipfileからrequirements.txtを生成しておく。

$ pipenv lock -r > requirements.txt 

.gcloudignoreを作成する

PipfileおよびPipfile.lockがあるままデプロイしようとすると、以下のようにエラーになってしまう。そこで、デプロイ不要なファイルとして登録しておく必要がある。

ERROR: (gcloud.app.deploy) INVALID_ARGUMENT: File 'Pipfile' is not supported.

デプロイ不要なファイルは.gcloudignoreという名前のファイルにパスを記載する。

.gcloudignore

# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
#   $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore

# Python pycache:
__pycache__/
# Ignored by the build system
/setup.cfg

Pipfile
Pipfile.lock

以上でGoogle App Engineにデプロイするためのファイルを作成した。

Cloud SDKをインストールする

Cloud SDKをインストールする。
すでにインストール済みの場合、次のコマンドでgcloudコマンドを最新にする。

$ gcloud components update

プロジェクトを作成する

gcloud projects create プロジェクト名でプロジェクトを作成する。

gcloud projects create gae-flask-app

次のコマンドでプロジェクトが生成されたことを確認する。
プロジェクトが生成されると、生成時間やprojectIdなどが表示される。

$ gcloud projects describe gae-flask-app
createTime: '2019-05-09T11:56:23.457Z'
lifecycleState: ACTIVE
name: gae-flask-app
projectId: gae-flask-app
projectNumber: '559536975662'

Google App Engineを有効にする

gcloud app create --project=プロジェクト名でGoogle App Engineを有効化する。
リージョンの選択肢が表示されるので東京リージョン(asia-northeast1)を選択する。

$ gcloud app create --project=gae-flask-app
Please choose the region where you want your App Engine application
located:

 [1] asia-east2    (supports standard and flexible)
 [2] asia-northeast1 (supports standard and flexible)
 [3] asia-northeast2 (supports standard and flexible)
 ...略

最終的なデプロイ前のディレクトリ構成は以下の通り。

ディレクトリ

.
├── Pipfile
├── Pipfile.lock
├── __pycache__
│   └── main.cpython-37.pyc
├── app.yaml
├── main.py
├── requirements.txt
└── templates
    └── index.html

gcloud app deploy --project プロジェクト名でデプロイする。

gcloud app deploy --project gae-flask-app

しかし、Cloud Build APIを有効にしろとエラー表示される。

$ gcloud app deploy --project gae-flask-app
ERROR: (gcloud.app.deploy) Error Response: [7] Access Not Configured. Cloud Build has not been used in project gae-flask-app before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/cloudbuild.googleapis.com/overview?project=gae-flask-app then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.

エラーメッセージのURLをクリックし、Google Cloudのコンソールを開く。
Cloud Build APIの「有効にする」ボタンをクリックすると、課金が必要ですというモーダルが表示される。「課金を有効にする」ボタンをクリックして、APIを有効にする。

Google Cloudの画面でdeployを許可する

さて、Cloud Build APIを有効にしたら、再度デプロイコマンドを実行する。
今度はデプロイできた!

$ gcloud app deploy --project gae-flask-app
...略
Deployed service [default] to [https://gae-flask-app.appspot.com]

HTMLへのアクセス、APIへのアクセスともに成功している。感動。

GAEでHTMLが表示できる GAEでJSONが返ってくる

プロジェクトの削除

確認のためにつくったプロジェクトなので最後に削除しておく。

$ gcloud projects delete gae-flask-app

・参考
https://cloud.google.com/appengine/docs/standard/python3/testing-and-deploying-your-app
https://cloud.google.com/appengine/docs/standard/python3/config/appref
http://docs.gunicorn.org/en/stable/settings.html#bind