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 build
、sam 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も動作します。
Lambdaはレスポンスのサイズに制限がありますが、 ちょっとしたWebアプリの作成なら、Lambdaだけでできそうです。