DashをAWS Lambda上にZappaでデプロイする

目次

データ分析WebアプリケーションフレームワークであるDashをAWS Lambda(以下Lambda)上にデプロイする方法について説明します。 LambdaへのデプロイはZappaを使って行います。

Dashについて

DashはPlotly Technologies社によって開発されているデータ分析Webアプリケーションフレームワークです。同じく同社が開発しているデータ可視化ライブラリであるPlotly.jsを使用したWebアプリケーションを効率的に作成できます。

今回はこのDashを使ったアプリケーションをLambada上にデプロイし、サーバレスでデータ分析のダッシュボードを作る手順を説明します。

Zappaについて

Zappaは、pythonのwebアプリケーションをAmazon API Gateway(以下API Gateway)とLambda上で動かせるようにしてくれます。つまり、Flaskのような常時立ち上がっていることを想定しているWebアプリケーションをアクセスがあったときだけ起動するイベント駆動のサーバレスアプリケーションとして運用できることになります。その結果、アイドル時のコストを削減することができます。

Dashのサンプルアプリケーションの用意

仮想環境の構築

Zappaが仮想環境を前提とするため、仮想環境を作ります。

python3 -m venv xxx
source xxx/bin/activate

Dashのインストール

python3 -m pip install dash plotly pandas 

Dashアプリケーション

Dashでの簡易なアプリケーションを記述します。

import plotly.express as px
import dash
from dash import html, dcc
from dash.dependencies import Input, Output

# サンプルデータを読み込む
df = px.data.gapminder()

# アプリケーションを作成する
app = dash.Dash(__name__)

# グラフを作成する
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("gapminder data"),
    html.Div([
        dcc.Graph(id='graph-1'),
        dcc.Graph(id='graph-2'),
        dcc.Graph(id='graph-3')
    ]),
    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'),
     Output('graph-2', 'figure'),
     Output('graph-3', 'figure')],
    [Input('x-column', 'value'),
     Input('y-column', 'value')])
def update_graph(x_col, y_col):
    fig1 = create_graph(df, x_col, y_col)
    fig2 = create_graph(df, y_col, x_col)
    fig3 = create_graph(df, 'year', y_col)
    return fig1, fig2, fig3

dapp = app.server.wsgi_app

if __name__ == '__main__':
    app.run_server(debug=True, host="0.0.0.0")

詳細な説明は割愛しますが、3つのグラフを表示するものになります。

ポイントは2点です。

  1. ローカル環境で確認するときは、
 app.run_server(debug=True, host="0.0.0.0")

により、サーバが立ち上がります。

  1. Zappaでは、API GatewayのイベントをLambdaのイベントとしてバイパスするために、アプリケーションのインスタンスを指定する必要があります。そのために、
dapp = app.server.wsgi_app

のようにして、アプリケーションのインスタンスを変数dappに入れています。

このファイルをapp.pyとして保存します。

python3 app.py

でアプリケーションが立ち上がるので、ブラウザでhttp://localhost:8050/にアクセスして表示されれば成功です。

ZappaでAWS環境上にデプロイ

前提としてIAMのアクセスキーなどは設定済みとします。

Zappaのインストール

python3 -m pip install zappa

Zappaの設定ファイルの用意

{
    "dev": {
        "app_function": "app.dapp",
        "project_name": "任意のproject名",
        "aws_region": "ap-northeast-1",
        "runtime": "python3.9",
        "s3_bucket": "任意のバケット名",
        "environment_variables": { "DASH_REQUESTS_PATHNAME_PREFIX": "/dev/" },
        "memory_size": 512,
        "timeout_seconds": 30,
        "keep_warm": false
    }
}

これをzappa_settings.jsonとして保存します。 ポイントとしては、

app_functionに先ほどのpythonのスクリプトファイルであるapp.pyのアプリケーションインスタンスを師弟するために、

"app_function": "app.dapp"

として指定しています。

また、 API Gatewayは、ステージ名をURLに含めないといけないため、

https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev

の形式でアクセスすることになるので、 DashでのjavascriptなどのアセットのURLを/dev/配下にするために、

"environment_variables": { "DASH_REQUESTS_PATHNAME_PREFIX": "/dev/" },

を指定しています。

Zappaのデプロイ

ここまで準備ができれば、

zappa deploy dev

でデプロイできます。 実行が完了すると、

https://xxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/dev

のようにURLが表示されるので、アクセスして以下の様な画面が表示できれば成功です。

代替テキスト