🌎

EC2インスタンス上でFastAPIを使ってみた

2023/09/16に公開

やったこと

FastAPIを使って簡単なAPIを作ってみました.

今日も今日とてn番煎じ.

取得できるデータは,現在Plicyさんに公開しているゲームのデータセットです.実はこのゲームの問題と選択肢のデータセットはJSON形式で作って,C#で呼び出して,Unityのテキストボックスやボタンに反映させています.
「実は…」と前置きするレベルのものではないですが.

https://plicy.net/GamePlay/156759

使った環境とかバージョンとか

  • MacBook Air M1 2020
  • ラズパイ4
  • AWS EC2インスタンス
    • OSはRHEL(バージョンは追々更新します)
  • Python3.9.12 (Macbookは確認したけど,EC2インスタンスの方は追々更新します)

Pythonのコードとか準備



from fastapi import FastAPI
import json

app = FastAPI()

#公開データ
with open("DATA.json") as f:
    data = json.load(f)


@app.get("/")
async def root():
    return data


上記コードはネットに多く転がっているというか,FastAPI公式にも記載されているコードにjsonの部分を付け足しただけです.

公開するJSONデータは,ホームディクトリ直下にTESTディレクトリを作成して,その直下に配置しました.

TEST
├ main.py
└ DATA.json



fastapiをインストールする必要があります.
ASGI なるものもインストールしておく必要があります.
ASGIなる言葉を初めて知ったのですが,wikipediaによると

Asynchronous Server Gateway Interface は、Web サーバーが要求を非同期対応の Python プログラミング言語フレームワークおよびアプリケーションに転送するための呼び出し規約です。

だそうです.


pip install fastapi
pip install "uvicorn[standard]"


そして,基本的にローカルで確認する場合は,上記インストールおよびファイルを配置して,以下をコマンドから実行し,localhost:8000にhttpアクセスしてデータが見れるかを確認したり,curl打ったり,pythonだったらrequestsモジュールでGETしてみたりで確認できます.(確認方法は割愛です)

uvicorn main:app --reload 


躓きポイント

当初はうまくいきませんでした.

ポートが既に使用中のエラー

reloadしたらエラー発生.
ポートが使われているというエラーでした.

ちょっと余談です.
インスタンス自体は,最近勉強中のterraformでreloadまで作成してしまおうかと思っておりました.
ですが,MacbookとEC2インスタンスの通信においてvpcとかセキュリティグループ周りのセキュリティをある程度担保しつつ検証したかったため,勉強中のterraformを使うのは少し怖くなり,既存の停止中のEC2インスタンスを起動しました.

それで,EC2インスタンスを起動したらポート8000番が使われてしまっている.
SaaS製品が動いてました.

++対処方法++

uvicorn main:app --port 8001 --reload 



このようにポート番号をデフォルトの8000番からずらしました.

起動したけどつながらない

セキュリティグループで8001番をanyから許可(一時的に)
サーバの方もfirewalldのルールに8001/tcpを許可しました.
ネットワークACLも確認済みです.

それなのにcurlすると拒否されました.

一旦ローカルでやってみる

セキュリティグループやサーバ側のセキュリティレベルを下げた状態で,問題解消の時間を費やすのも嫌だったため,自宅のネットワーク内で試してみることにしました.

そこで利用したのが,上にも記載したラズパイ4です.
EC2インスタンスを使っていた時は,Macbookがクライアントでしたが,今度はラズパイがクライアントです.MacBookがAPIサーバです.

ラズパイからMacBookのipの8000番に向かってcurlしました.
だが繋がらない.

reloadした状態でnmapをラズパイから使いました.
nmapはポートスキャンができる脆弱性診断ツールです.
自分も使いこなせていないのですが,自称セキュリティエンジニアなのでラズパイにしっかり入っています.
話が脱線しましたが,8000は空いてなさそうでした.

公式ドキュメントやGoogle検索をするのが今までのエラー解消方法でしたが,最近は面倒臭すぎてChatGPTに聞いちゃってます.
そして今回も聞いたところ,デフォルトで127.0.0.1のインターフェースがバインドされているからとの回答…魔剤?
--host 192.168.xx.xxのオプション追加したところ…
curl成功しました!

ちなみにhostオプションを追加した状態でサーバを起動していると,nmapしたところ8000番が空いていることを確認でき,ctrl+Cで止めれば8000番は閉じていることも確認できました.

というわけで hostオプション を使います.

再チャレンジ

セキュリティグループの設定を変えます.

そして,以下コマンドを打ちます.

uvicorn main:app --host xx.xx.xx.xx --port 8001 --reload 


hostはインスタンスのパブリックIPにしました.
するとエラー.割り当てられないとのこと.
ChatGPTは出来るって言っているけど?

今度は普通にGoogle検索したところ,海外の方が質問されているものを発見.
0.0.0.0にしていたため,真似してみると起動完了.

無事JSONデータをGETできました!

所感

APIがこんなにサクッと作れることに驚きました.
というか,自分が提供できるようなリソースがあったことにも驚いている.

今回使ったfastapi,ASGI,AWS,ラズパイ,namp…と表面上でしか理解,使用できておらず,まだまだ探求の余地ありです.
とはいえ,他にも触りたい言語とかあるし,何事も1回じゃ覚えられない脳みそだから何回か書籍とかUdemyとか受講しなきゃいけないという感じで,時間が足りないです

ちゃぶ台返しにはなるが…

AWSでAPIを作るならlambdaとAPI gatewayを使うのが主流らしいです.あとCognitoとかも??

EC2インスタンスを起動したままだとお金かかりますからね…
特に自分みたいに個人で契約している場合厳しいです.

お恥ずかしい話,lambda,API gatewayともに使ったことがないので,勉強してみようと思います.
(追記)lambda,API gatewayの組み合わせの方がプロトタイプはかなり容易に出来た気がします.Cognito周りが少し難しかったです…

GitHubで編集を提案

Discussion