schedule2018-07-06

Zappaを使ってPythonのコードをAWS Lambdaにデプロイする

この記事の目的

Python + FlaskのアプリをZappaを使ってAWS Lambdaにデプロイして、動作確認まで行います。 macでの環境の構築をメインに、丁寧に書いていきます。

Zappaとは

GitHub:Zappa

ZappaはコマンドラインでPythonのWSGIアプリケーションをデプロイできます。 AWSではLambdaに、また、他ののクラウドにも対応しています。

Lambdaでは直接コードを書く場合と、コードとライブラリをまとめたZIPファイルをアップロードしてデプロイします。 Zappaではvirtualenvの仮想環境をZIPファイルにまとめて、デプロイします。ZIPの作成も自動的に行なってくれるのでとても簡単です。

自分でZIPファイルにまとめてデプロイも可能です。 zipコマンドについてはこちら

デプロイの様子.gif デプロイの様子 : Zappaより

必要な環境さえ整えれば、GIFの通り簡単にAWSにコードをデプロイすることができます。

日本語の記事では、zappa で hello world するまでが参考になります。CentOS7で確認されていますので、Redhat系の方はこちらの手順で進めて見てください。公式からもリンクされており、公認みたいです。

公式を翻訳しているサイトZappa – サーバーレスPythonもあります。応援しています‼️

環境

  • macOS High Sierra
  • Python3.6.5
  • pyenv 1.2.3

流れ

  1. pyenvとpyvirtualenvのインストール
  2. Python3.6の準備
  3. AWSのIAMの設定
  4. デプロイする仮想環境の構築
  5. アプリケーションの用意
  6. Zappaのインストールとデプロイ

手順

1. pyenvとpyvirtualenvのインストール

まずは、仮想環境を用意しましょう。

macではパッケージマネージャーのHome Brewを使ってツールをインストールします。Home Brewがまだない方は、こちらのスクリプトをコピーして、実行してください。

Home Brewをインストールできたら下記の手順でpyenvとpyvirtualenvのインストールを進めます。

$ brew install pyenv
$ brew update && brew upgrade pyenv
pyenv 1.2.1 -> 1.2.3

$ brew install pyenv-virtualenv
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

echo ...でpyenvをログイン時に起動するよう書き込み、exec ...で即時起動しています。(たぶん。。。)

2. Python3.6の準備

続いて、macの環境をPython3.6にしておきましょう。 macにはデフォルトで2.7が入っています。変えたくない方や、他のバージョンを使っている方は飛ばしてください。

$ pyenv install 3.6.5
# 全体に反映
$ pyenv global 3.6.5
$ python --version
Python 3.6.5

python3.6が確認できたら、pipもアップグレードしておきます。aws cliをインストールするのに使います。

$ pip -V
pip 9.0.3 from /Users/{user}/.pyenv/versions/3.6.5/lib/python3.6/site-packages (python 3.6)
$ pip install -U pip
Successfully installed pip-10.0.1

3. AWSのIAMの設定

AWSにデプロイするためには、アクセスできるユーザとサービスの操作を許可するIAMの設定が必要です。

コンソールからデプロイ用のユーザを作成し、アクセスキーとシークレットキーを保管してください。 IAMの設定でユーザに操作の許可を与えてください。Lambda、S3、API GatewayのFullaccessは必要。その他、利用するサービスの権限を与えて下さい。

Minimum AWS policies for example. こちらにpermission policieの例が載っています。

ターミナルに戻って、キーの設定を行います。

$ pip install awscli
$ aws configure
AWS Access Key ID [********************]:
AWS Secret Access Key [********************]:
Default region name [ap-northeast-1]:
Default output format [json]:

aws configureでアクセスキーなどを聞かれるので、打ち込んであげてください。 regionは東京にしました。

4. デプロイする仮想環境の構築

Lambdaには仮想環境ごとライブラリをまとめてデプロイします。 フォルダごとに仮想環境を用意しておくと何かと便利なので、ローカル環境を作成します。

$ pyenv virtualenv 3.6.5 bar
$ mkdir foo
$ cd foo
$ pyenv local bar

(bar) $ となっていれば成功。

fooというフォルダを用意して、そこにローカル環境barを作成しています。 fooとローカル環境には適当な名前をつけて下さい。

※注意 仮想環境の名前はZappaのプロジェクト名と同じものを使用しないで下さい。エラーが起こり得ます。

ここまでは、macで別のバージョンのpythonを使うとき便利です。

ローカル環境もpipを最新にしておきます。

$ pip install -U pip
Successfully installed pip-10.0.1

5. アプリケーションの用意

Flaskを使ってhello from Flask!を返す簡単なアプリを作成します。

仮想環境を用意したディレクトリfooに、app.pyを作成します。

foo/app.py

from flask import Flask

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def lambda_handler(event=None, context=None):

    return 'hello from Flask!'

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

fooに移動して、ライブラリをインストールして確かめて見ましょう。

$ cd foo
$ pip install flask
Successfully installed Flask-1.0.2 Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 itsdangerous-0.24
$ pip freeze
click==6.7
Flask==1.0.2
itsdangerous==0.24
Jinja2==2.10
MarkupSafe==1.0
Werkzeug==0.14.1

$ python app.py
 * Serving Flask app "app" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

http://127.0.0.1:5000/をブラウザで開いて確認して見てください。 hello_flask_local

6. Zappaのインストールとデプロイ

とうとう、デプロイするところまできました。 まずは、Zappaをインストールして設定を行います。

$ pip install zappa
$ zappa init

███████╗ █████╗ ██████╗ ██████╗  █████╗
╚══███╔╝██╔══██╗██╔══██╗██╔══██╗██╔══██╗
  ███╔╝ ███████║██████╔╝██████╔╝███████║
 ███╔╝  ██╔══██║██╔═══╝ ██╔═══╝ ██╔══██║
███████╗██║  ██║██║     ██║     ██║  ██║
╚══════╝╚═╝  ╚═╝╚═╝     ╚═╝     ╚═╝  ╚═╝

Welcome to Zappa!

設定は全てEnterを押してデフォルトにすると以下のzappa_settings.jsonが作成されます。 フォルダ名がプロジェクト名になっています。

Okay, here's your zappa_settings.json:

{
    "dev": {
        "app_function": "app.app",
        "aws_region": "ap-northeast-1",
        "profile_name": "default",
        "project_name": "foo",
        "runtime": "python3.6",
        "s3_bucket": "zappa-9jex9436c"
    }
}
Does this look okay? (default 'y') [y/n]: y

$ ls
app.py                  zappa_settings.json

※注意(再掲) 仮想環境の名前はZappaのプロジェクト名と同じものを使用しないで下さい。エラーが起こり得ます。

注意点として、実行ファイルの名前を合わせる必要があります。 zappa_setting.jsonの"app_function"を"{実行するファイル名}.app"として下さい。hello.pyを実行する場合は次のようにします。"app_function": "hello.app",

デプロイします。

$ zappa deploy
Deployment complete!: https://81dc4kiste.execute-api.ap-northeast-1.amazonaws.com/dev

成功すると、API GatewayのURLが表示されます。 hello_flask_lambda

AWSのコンソールからLambdaを確認するとfoo-devという関数が作られていました。 lambda

※私の環境ではpermission policieにDynamoDBなども含めているので、Lambdaからアクセスできるようになっています。

アップデートもしてみましょう。 せっかくなので、URLで応答を変えるようにします。 hello_name()の関数を追加しました。

foo/app.py

from flask import Flask

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def lambda_handler(event=None, context=None):
    
    return 'hello from Flask!'

@app.route('/<name>', methods=['GET', 'POST'])
def hello_name(name):
    
    return 'hello ' + name

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

アップデートします。

$ zappa update

URLの末尾に文字を入れてください。

update

その他、ログを監視するtailや前のバージョンにロールバックするrollbackなど便利なコマンドがあります。 zappa -hで確認してください。

zappaの導入手順は以上となります。

同様のライブラリ

Chalice

こちらはAWSのためのAmazon製のサーバレスマイクロフレームワーク。LambdaとAPI Gatewayのデプロイができるようです。

Zappaとの比較はこちらの記事が参考になりました。 Python サーバーレスフレームワークの比較 - Zappa vs Chalice

終わりに

Pythonでサーバレスな開発を行うなら、zappaがとても便利だと思います。 ただ、日本語の情報が少ないので、躓いたとき辛いです。。。 少しでも参考になれば、幸いです。


サーバレスアーキテクチャを勉強される方は、こちらの本がおすすめです。

動画シェアサイトをAWS Lambda, S3を使って実際に構築する手順が載っています。 その中で、どのようにLambdaを構成したら良いか大変参考になりました。また、DynamoDBとAuth0も詳しく書かれています。