Python DashアプリをAWS Lambdaにデプロイする完全ガイド

AWS SAMを使用したデプロイ方法

AWS SAMを使用したPython Dashアプリのデプロイ

AWS SAMとは

AWS SAM(Serverless Application Model)は、サーバーレスアプリケーションを構築するためのオープンソースフレームワークです。AWS CloudFormationの拡張として機能し、サーバーレスアプリケーションのインフラストラクチャをコードとして定義することができます。

SAMを使用することで、以下のメリットがあります:

前提条件

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

対話式のプロンプトが表示されるので、以下のように選択します:

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

対話式のプロンプトが表示されるので、以下のように設定します:

デプロイが完了すると、以下のような出力が表示されます:

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.yamlDashFunctionに以下の設定を追加します:

      Environment:
        Variables:
          VARIABLE_NAME: variable_value

リソースの追加

DynamoDBなどの追加リソースを使用する場合は、template.yamlResourcesセクションに追加します:

  DashTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: dash-data
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH

トラブルシューティング

ビルドエラー

ビルド中にエラーが発生した場合は、以下を確認してください:

デプロイエラー

デプロイ中にエラーが発生した場合は、以下を確認してください:

ログの確認

Lambda関数のログを確認するには、以下のコマンドを実行します:

sam logs -n DashFunction --stack-name dash-lambda-app --tail