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

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

この記事では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 (opens new window)

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

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 リクエストを受信するポートだ。
その他の環境変数は、こちら (opens new window)で確認できる。

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 (opens new window)

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

$ pipenv lock -r > requirements.txt 

# .gcloudignoreを作成する

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

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

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

.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 (opens new window)をインストールする。
すでにインストール済みの場合、次のコマンドで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 (opens new window)
https://cloud.google.com/appengine/docs/standard/python3/config/appref (opens new window)
http://docs.gunicorn.org/en/stable/settings.html#bind (opens new window)