AWS SAMを使用したPython Dashアプリのデプロイ
AWS SAMとは
AWS SAM(Serverless Application Model)は、サーバーレスアプリケーションを構築するためのオープンソースフレームワークです。AWS CloudFormationの拡張として機能し、サーバーレスアプリケーションのインフラストラクチャをコードとして定義することができます。
SAMを使用することで、以下のメリットがあります:
- インフラストラクチャをコードとして管理(IaC)
- ローカル環境でのテストとデバッグが可能
- AWS CloudFormationとの互換性
- CI/CDパイプラインとの統合が容易
前提条件
- AWS CLIがインストールされ、設定済みであること
- AWS SAM CLIがインストールされていること
- Python 3.6以上がインストールされていること
- Docker(ローカルテスト用、オプション)
AWS SAM CLIのインストール
# Linuxの場合
pip install aws-sam-cli
# macOSの場合
brew tap aws/tap
brew install aws-sam-cli
# Windowsの場合
pip install aws-sam-cli
プロジェクトのセットアップ
1. SAMプロジェクトの初期化
sam init --runtime python3.9 --name dash-lambda-app
対話式のプロンプトが表示されるので、以下のように選択します:
- テンプレートタイプ: AWS Quick Start Templates
- パッケージタイプ: Zip
- ランタイム: Python 3.9
- アプリケーションテンプレート: Hello World Example
2. プロジェクト構造
初期化後、以下のようなプロジェクト構造が作成されます:
dash-lambda-app/
├── README.md
├── events/
│ └── event.json
├── hello_world/
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── samconfig.toml
├── template.yaml
└── tests/
└── unit/
├── __init__.py
└── test_handler.py
3. 依存関係のインストール
hello_world/requirements.txt
を編集して、必要なパッケージを追加します:
dash==2.14.0
plotly==5.18.0
pandas==2.1.1
werkzeug==2.3.7
flask==2.2.5
aws-wsgi==0.2.7
Dashアプリケーションの作成
hello_world/app.py
を以下の内容に置き換えます:
import plotly.express as px
import dash
from dash import html, dcc
from dash.dependencies import Input, Output
import aws_wsgi
# サンプルデータを読み込む
df = px.data.gapminder()
# アプリケーションを作成する
app = dash.Dash(__name__, requests_pathname_prefix='/Prod/')
# グラフを作成する関数
def create_graph(data, x_col, y_col):
fig = px.scatter(data, x=x_col, y=y_col, color='continent',
log_x=True, size_max=60, title=f"{y_col} vs {x_col}")
return fig
# レイアウトを定義する
app.layout = html.Div([
html.H1("Dash App on AWS Lambda with SAM"),
html.Div([
dcc.Graph(id='graph-1')
]),
html.Div([
dcc.Dropdown(
id='x-column',
options=[{'label': i, 'value': i} for i in df.columns],
value='gdpPercap'
)
], style={'width': '25%', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
id='y-column',
options=[{'label': i, 'value': i} for i in df.columns],
value='lifeExp'
)
], style={'width': '25%', 'display': 'inline-block'}),
])
# コールバックを定義する
@app.callback(
Output('graph-1', 'figure'),
[Input('x-column', 'value'),
Input('y-column', 'value')])
def update_graph(x_col, y_col):
fig = create_graph(df, x_col, y_col)
return fig
# Lambda関数のハンドラー
def lambda_handler(event, context):
return aws_wsgi.response(app.server, event, context)
# ローカルテスト用
if __name__ == '__main__':
app.run_server(debug=True, host="0.0.0.0")
重要なポイント:
requests_pathname_prefix='/Prod/'
: API Gatewayのステージ名(Prod)に合わせてパスプレフィックスを設定します。aws_wsgi
: API GatewayのイベントをFlask/Dashアプリケーションに変換するためのライブラリです。lambda_handler
: Lambda関数のエントリーポイントとなる関数です。
SAMテンプレートの設定
template.yaml
を以下の内容に編集します:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
dash-lambda-app
Python Dash application deployed on AWS Lambda using SAM
Globals:
Function:
Timeout: 30
MemorySize: 512
Runtime: python3.9
Resources:
DashFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Architectures:
- x86_64
Events:
DashAPI:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
DashRoot:
Type: Api
Properties:
Path: /
Method: ANY
Outputs:
DashFunction:
Description: "Lambda Function ARN"
Value: !GetAtt DashFunction.Arn
DashApi:
Description: "API Gateway endpoint URL for Prod stage"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
DashFunction:
Description: "Lambda Function Name"
Value: !Ref DashFunction
テンプレートの重要なポイント:
Timeout: 30
: Lambda関数のタイムアウトを30秒に設定します。MemorySize: 512
: Lambda関数のメモリサイズを512MBに設定します。Events
: API Gatewayのイベントを設定します。ルートパス(/)とプロキシパス(/{proxy+})の両方を設定することで、すべてのリクエストをLambda関数にルーティングします。
ビルドとデプロイ
1. アプリケーションのビルド
sam build
このコマンドは、アプリケーションのコードと依存関係をビルドし、デプロイ可能なパッケージを作成します。
2. ローカルでのテスト(オプション)
sam local start-api
このコマンドは、ローカル環境でAPI Gatewayとアプリケーションをエミュレートします。http://localhost:3000
にアクセスして、アプリケーションをテストできます。
3. デプロイ
sam deploy --guided
対話式のプロンプトが表示されるので、以下のように設定します:
- スタック名: dash-lambda-app
- AWS リージョン: ap-northeast-1(または任意のリージョン)
- 確認プロンプト: Y
- IAMロールの作成許可: Y
- デプロイ設定の保存: Y
デプロイが完了すると、以下のような出力が表示されます:
CloudFormation outputs from deployed stack
---------------------------------------------------------
Outputs
---------------------------------------------------------
Key DashApi
Description API Gateway endpoint URL for Prod stage
Value https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/
---------------------------------------------------------
表示されたURLにアクセスして、Dashアプリケーションが正常に動作していることを確認します。
更新と削除
アプリケーションの更新
アプリケーションを更新する場合は、コードを変更した後、以下のコマンドを実行します:
sam build
sam deploy
アプリケーションの削除
アプリケーションを削除する場合は、以下のコマンドを実行します:
aws cloudformation delete-stack --stack-name dash-lambda-app
このコマンドを実行すると、CloudFormationスタックとそれに関連するすべてのリソース(Lambda関数、API Gateway、IAMロールなど)が削除されます。
高度な設定
カスタムドメインの設定
template.yaml
に以下の設定を追加します:
ApiGatewayDomainName:
Type: AWS::ApiGateway::DomainName
Properties:
DomainName: your-domain.com
CertificateArn: your-certificate-arn
ApiGatewayBasePathMapping:
Type: AWS::ApiGateway::BasePathMapping
Properties:
DomainName: !Ref ApiGatewayDomainName
RestApiId: !Ref ServerlessRestApi
Stage: Prod
環境変数の設定
template.yaml
のDashFunction
に以下の設定を追加します:
Environment:
Variables:
VARIABLE_NAME: variable_value
リソースの追加
DynamoDBなどの追加リソースを使用する場合は、template.yaml
のResources
セクションに追加します:
DashTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: dash-data
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
トラブルシューティング
ビルドエラー
ビルド中にエラーが発生した場合は、以下を確認してください:
- 依存関係が正しく記述されているか
- Python バージョンが互換性があるか
- 必要なパッケージがすべて含まれているか
デプロイエラー
デプロイ中にエラーが発生した場合は、以下を確認してください:
- AWS認証情報が正しく設定されているか
- 必要なIAM権限があるか
- CloudFormationテンプレートの構文が正しいか
ログの確認
Lambda関数のログを確認するには、以下のコマンドを実行します:
sam logs -n DashFunction --stack-name dash-lambda-app --tail