はじめに

StreamlitをAWSのコンテナサービスで軽く動かしたいとなったときに、AWS Lambda単体やAWS App RunnerではWebSocketが使えないため動かせません。
かといってECSを持ち出すのもちょっと億劫だったのでAmazon Lightsail コンテナサービスにデプロイできるか試してみました。

コンテナイメージの作成

まずは簡単なStreamlitアプリケーションを作ってコンテナイメージをビルドします。

app.py

import streamlit as st

st.title("Sample Amazon Lightsail Streamlit App")

name = st.text_input("What's your name?")

if st.button("Submit"):
    st.write(f"Hello, {name}! Welcome to Streamlit on Amazon Lightsail.")

Dockerfile

FROM python:3.12-slim

WORKDIR /app

COPY . /app

RUN pip install --no-cache-dir streamlit==1.39.0

EXPOSE 8501

CMD ["streamlit", "run", "app.py", "--server.port=80"]

イメージをビルドして動作を確認。

docker buildx build --platform linux/amd64 -t streamlit-sample .
docker run -p 80:80 streamlit-sample

問題なく動作していれば、次にコンテナイメージを保存するためのコンテナレジストリをECRに作成しイメージをプッシュします。

下記のコマンドは例なので自身の環境にあわせて修正してください。

aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag streamlit-sample:latest 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/streamlit-sample:latest
docker push 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/streamlit-sample:latest         

Amazon Lightsail コンテナサービスにデプロイ

コンテナサービスを作成

コンソールからコンテナサービスを作成します。
ここでコンテナサービス名に数字が使われているとなぜかECRへの権限付与で失敗したのでデフォルトの名前から変えておきましょう。

試すだけなので最小構成のNanoで、月額7ドルと手頃に利用することができます。

ECRを使うのでデプロイのセットアップは後で行います。

イメージのデプロイ

コンテナサービスが作成されたら、「イメージ」タブから事前に作ったECRのプライベートリポジトリを使うよう設定します。

リポジトリへのアクセス権が自動的に付与されます。

リポジトリのURLが取得できるのでこれを使って「デプロイ」タブからイメージのデプロイを設定します。

リポジトリのURLとHTTPの80ポートを開放してヘルスチェックを設定しデプロイします。

デプロイが成功したらパブリックドメインからアクセスして動作を確認しましょう。

Amazon Lightsail コンテナサービスでStreamlitが動作することが確認できました!

注意

ただし、この構成はAmazon Lightsailのインスタンスと違いファイアウォールルールを設定できず、AWS WAFも関連付けられないためIP制限が行えません。
IP制限したい場合はECS/EKSを使うか、ログイン認証などをStreamlitアプリ自体に持たせるのがよいでしょう。
ECSを利用したStreamlitの構成はGitHubにAWSのサンプルリポジトリがいくつかあります。

AWS App RunnerがAWS WAFを設定できるのでWebSocket対応が待ち遠しいですが、今のところ予定はなさそうな雰囲気です。