🥕

【AWS】Pythonで書いたWebアプリをApp Runnerで動かす【Flet, Flutter】

2024/03/15に公開

はじめに

AIを中心としたアプリ開発をする時はPythonが主流かと思います。一方でWebのフロントエンド開発は通常TypeScriptやJavaScriptで書く必要があります。ある程度規模の大きいアプリであれば、フロントエンドとバックエンドは分離するべきなので言語が分かれていても大きな問題はないかと思います。
しかし、PoCなどの簡易的にアプリを作りたい場合にはコスト増や人的リソースの問題が出てきます。Streamlit等のモダンなPythonのWebフレームワークを使えばPythonのみでWebアプリを作ることが出来ます。しかし、これらのフレームワークはWebSocketに依存しいる為、AWS App RunnerなどのWebSocketに対応していないサービス上では動きません。
https://zenn.dev/ncdc/articles/71d49bced3b69d
過去の記事ではAWSをあきらめてCloud Runで動かしましたが、「なんとかならないかな?」と思っていました。

FletというPythonのフレームワークを使うとなんとかなりそうなので、紹介します。

Fletでアプリを作る

Fletとは

https://flet.dev

Fletとは、PythonでFlutterアプリを作ることができるフレームワークです。
Flutterなので、モバイル、デスクトップアプリ、Webの全てに対応可能です。すごい!

動かしてみた

今回は動かすことが目的なので、Fletのドキュメント1ページ目に記載されているコードをコピペして動かします。
https://flet.dev/docs/

書きました

GitHubに置いたので、詳細はそちらをご参照ください。
https://github.com/k-ibaraki/flet-sample/tree/main/app
動かし方はReadme参照です。

コピペしたソースコード

https://github.com/k-ibaraki/flet-sample/blob/main/app/src/flet_sample/run_app.py

動かしました

まず、パッケージをインストールします。
今回は、パッケージ管理ツールのryeを使いましたので、以下のコマンドでアプリに必要なPythonライブラリをインストールすることができます。

rye add flet
rye sync

なお、pipでfletをインストールしたい場合はpip install fletでOKです。

アプリ起動します。

rye run python main.py

main.pyはこんな感じです。
https://github.com/k-ibaraki/flet-sample/blob/main/app/main.py

起動するとブラウザが開きます。

ドキュメント通りのアプリですね。無事に動きました。

webアプリとしてビルドする

このままコンテナ化すればよいのでは?と思ってしまうのですが、問題があります。
起動コマンドから分かるようにPythonから起動しています。そうすると他のモダンなPythonのWebフレームワーク同様にWebSocketを使用して動作してしまいますので、目的であるAWS AppRunner上では動きません(残念です)
ではどうするかですが、FletがFlutterに依存して動くこと利用し、Flutterでビルドすることで普通のhttpサーバー上で動くようにしてみました。

準備する

Flutterをインストールする

ビルドするにはFlutterの導入が必要になります。
Flutterのドキュメントを参考にインストールして、CLIでflutterコマンドが実行できる状態にしましょう。
https://docs.flutter.dev/get-started/install

Flet CLIでビルドする。

https://flet.dev/docs/cli/
FletのCLIを使ってビルドすることが出来ます。FletのCLIはFletをインストールした時点でついでにインストールされています。

rye run flet build web
Creating Flutter bootstrap project...OK
Customizing app icons and splash images...OK
Generating app icons...OK
Generating splash screens...OK
Packaging Python app...OK
Building web app...OK
Copying build to build/web directory...OK
Success!

ビルドできました。build/web配下に生成物があるので、普通のhttpサーバーを立ち上げて動かしてみましょう。

cd build/web
rye run python -m http.server

ブラウザで開くとアプリが動いていることが確認できます。

先ほどと全く同じアプリしか見えませんが、内部的な挙動は変わっておりWebSocketは使わずにhttpだけで動いています。

コンテナ化する

ここまで来たら、後はコンテナ化してAppRunnerにデプロイすればOKです。

Dockerfileを書く

Dockerfileを書きました。
https://github.com/k-ibaraki/flet-sample/blob/main/app/Dockerfile

中身はDockerfileを読んでいただければと思いますが、苦労した点を箇条書きで書いておきます。

  • Debian環境へのflutterのインストール。
    • 参考になる記事等とかが少なかったです。
  • flet build web実行時にrequirements.txtが残っていると何故か依存関係のエラーになる。
    • 何故そういう挙動をするのか意味不明です。
    • pip install後にrequirements.txtを削除したらビルドが通りました。

AWSにデプロイする

手動で頑張るのは辛いのでCDKでデプロイしました。

CDKを書く

書きました。
https://github.com/k-ibaraki/flet-sample/tree/main/cdk
CDKはTypeScriptで書きました。Pythonで書こうかとも思ったのですが、やっぱりTypeScriptのほうが慣れているので。。。

デプロイする

デプロイします。

npx cdk deploy --profile {AWS_PROFILE}

しばらく待ってAWSコンソールを見ると、App Runnerが出来ています。

URLにアクセスすると無事に動いています。

最後に

ここまで書いてから気づいたのですが、ビルドしたならコンテナ化してApp Runnerにデプロイするよりも静的ファイルをAmplifyにデプロイしたほうが良くないですか?

ということで、Amplify編に続きます
https://zenn.dev/ncdc/articles/28bce28b769b5b

NCDCエンジニアブログ

Discussion