AWS LambdaでPython+Flask環境を作成する


AWS SAM + Lambda + Python + Flask の環境を作成する方法を調べたのでメモにします。


環境

$ docker --version
Docker version 20.10.5, build 55c4c88
$ aws --version
aws-cli/2.1.34 Python/3.8.8 Linux/5.4.0-52-generic exe/x86_64.ubuntu.20 prompt/off
$ sam --version
SAM CLI, version 1.21.1

SAMでプロジェクトの作成

sam initでプロジェクトを作成します。
Zip形式、Image形式のでどちらでも大丈夫です。
構成:

.
├── README.md
├── hello_world
│   ├── app.py
│   ├── requirements.txt
│   ├── static
│   │   └── js
│   │       └── script.js
│   └── templates
│       └── index.html
├── samconfig.toml
└── template.yaml

Lambda関数の実装


テンプレート(template.yaml)の修正

ルーティングはFlaskのアノテーションを使いたいので、
API Gatewayの設定は、Path: '/{proxy+}'Method: ANYにしてすべてのリクエストを Lambda関数で処理できるようにします。
template.yaml:

  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: 'sample-flask'
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.8
      Events:
        ApiRoot:
          Type: Api
          Properties:
            Path: '/'
            Method: ANY
        ApiProxy:
          Type: Api
          Properties:
            Path: '/{proxy+}'
            Method: ANY

依存モジュールの設定

aws-wsgiを使用して、LambdaのeventをFlaskで処理できるようにします。

requirements.txt:

requests
Flask
aws-wsgi

参考URL:
AWSGI
https://github.com/slank/awsgi


Flaskアプリケーションの実装

lambda_handlerで、AWSGIを使用して、Flaskのアプリケーションを実行します。
それ以外は、通常のFlaskのアプリケーションと同様に実装します。

app.py:

import awsgi
from flask import Flask, request, render_template

app = Flask(__name__)

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

@app.route('/hello', methods=['GET'])
def hello_get():
    return {'msg': 'get method'}

@app.route('/hello', methods=['POST'])
def hello_post():
    return {'msg': 'post method'}

def lambda_handler(event, context):
    return awsgi.response(app, event, context)

templates/index.html

<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Hello Lambda</title>
  </head>
  <body>
    <h1>Hello Lambda</h1>
    <button onclick="helloLambda()">click me!!</button>
    <script src="static/js/script.js"></script>
  </body>
</html>

static/js/script.js

function helloLambda() {
    alert('Hello Lambda');
}

実行結果

sam buildsam deployでデプロイし実行した結果です。

GET /hello

$ curl https://XXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/hello
{"msg":"get method"}

POST /hello

curl -X POST https://XXXX.execute-api.ap-northeast-1.amazonaws.com/Prod/hello
{"msg":"post method"}

ブラウザでのアクセス
Javascriptも動作します。

/images/20210421.png

Screenshot


Lambdaはレスポンスのサイズに制限がありますが、 ちょっとしたWebアプリの作成なら、Lambdaだけでできそうです。


AWS  Lambda  SAM  Python  Flask 

See also