Streamlit Community CloudによるWebアプリ公開手順【画像付き】

# 0. はじめに
物体検出モデル YOLOv8 の学習を兼ねて「ポケモン図鑑」Webアプリを作成し、Streamlit Community Cloud (SCC) 上でデプロイしました。
本記事は、その外部公開方法にフォーカスした備忘録です。
推論モデル部分・Streamlitアプリ本体の実装は完了している前提で、
**「Streamlitアプリの公開手順」** に特化して解説します。

# 1. 前提条件・必要なもの
- 必要なアカウント一覧
    - GitHub
    - Hugging Face  
    - [Streamlit Community Cloud](https://qiita.com/D-SNOW/items/3cbe61fec00cec0c0ec3 "SCCアカウント開設方法")
- 事前準備・確認
    - YOLOv8 で学習済みモデルが用意できていること
    - Streamlit アプリがローカルで正常に動作していること

# 2. プロジェクト構成と必要ファイル
以下のようなディレクトリ構成で、ファイルを用意します。
特に問題がなければ app.py と requirements.txt の2つだけでOKです。
```bash
project-root/
├── app.py              # Streamlit本体
├── requirements.txt    # 必須パッケージ一覧
├── .gitignore          # 除外ファイル指定
└── packages.txt        # 補助スクリプト
```

# 3. requirements.txtの作成（依存パッケージ管理）
開発環境で利用している仮想環境が有効になっている状態で、以下のコマンドをターミナルで実行することで、
プロジェクトで使用している依存パッケージ一覧をrequirements.txtとして出力できます。
```python
pip freeze > requirements.txt
```

下記は、今回私の環境で作成したrequirements.txtの内容例です。
**バージョンは==で固定（ピン留め）** することを推奨します。
パッケージのアップデートによる予期しない挙動や互換性の問題を防ぐためです。
```requirements.txt
streamlit
ultralytics
pillow
numpy
opencv-python-headless==4.11.0.86
requests
huggingface-hub
```
:::note info
`huggingface-hub`は、Hugging Faceにアップロードした学習済みモデルをロードする際に必要です。
:::

:::note alert
Streamlit環境では、GUIを含むopencv-pythonをインストールするとエラーが発生する場合があります。
そのため、今回はGUI機能を含まないopencv-python-headlessを使用しています。
:::

:::note warn
Google Colaboratory（Colab）を開発環境として使用している場合、
`pip freeze > requirements.txt`を実行すると、
Colab環境にもともとインストールされている多数の不要なパッケージまで
`requirements.txt`に出力されてしまいます。
そのため、実際に自分のプロジェクトで利用しているパッケージだけを手動で記載するようにしましょう。
:::

# 4. packages.txtの用意（システムパッケージ追加）
画像処理系ライブラリ（OpenCVやYOLOなど）を扱う場合、SCC環境で以下のエラーが出ることがあります。

>ImportError: libGL.so.1: cannot open shared object file: No such file or directory

これを解消するために、以下2行を packages.txt に記載し、必ず[プロジェクトファイル構成](#2-プロジェクト構成と必要ファイル)のようにプロジェクトのルートディレクトリに配置してください。
```packages.txt
libgl1-mesa-glx
libglib2.0-0
```
- 必要に応じて他のシステムパッケージもここに追記します。

# 5. GitHubリポジトリ作成・プッシュ
## 5.1 新規リポジトリ作成
[GitHubのリポジトリ作成手順](https://qiita.com/D-SNOW/items/0ef84bf5b80bd4fbc223)に従って作成します。
## 5.2 ファイル配置＆プッシュ
`app.py`・`requirements.txt`・`packages.txt` など、必要なファイルを[プロジェクトファイル構成](#2-プロジェクト構成と必要ファイル)に従ってリポジトリに追加・プッシュしてください。

:::note info
リポジトリはパブリック・プライベートどちらでも作成できますが、SCCとGitHubの連携に注意してください。[こちら](https://qiita.com/D-SNOW/items/3cbe61fec00cec0c0ec3)を参照。
:::

下図のようなイメージで、GitHubのWeb画面で主要なファイルが正しく配置されていることを確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/10069f8b-ff45-43ea-add4-5aa02e7604f0.png)


# 6. 学習済みモデルの配置（Hugging Face連携）

## 6.1 モデルファイルはGitHubに置かない
GitHubでは50 MBを超えるファイルがアップロード制限にかかるため、学習済みモデルはHugging Faceにホストして利用する方法を採用しました。

## 6.2 Hugging Faceへ学習済みモデルアップロード
[アップロード手順はこちら](https://qiita.com/D-SNOW/items/3c95bf72569b620f2063)

## 6.3 Streamlitからモデルをダウンロード・利用する
`app.py`に下記のように記述します（Secrets対応）。
Streamlit 上から学習済みモデルを読み込むことができるようになります。
Streamlitの「Sectets」については後に説明します。
```python
import streamlit as st
from huggingface_hub import hf_hub_download, login
from ultralytics import YOLO

# ────────────
# 1. Hugging Face トークンの取得とログイン
# ────────────
# Streamlit の "Secrets" に保存したトークンを読み込み
hf_token = st.secrets["HUGGINGFACE_TOKEN"]

# Hugging Face 上で認証セッションを開始
login(token=hf_token)

# ────────────
# 2. モデル読み込み関数の定義
# ────────────
@st.cache_resource
def load_yolo_model(repo_id: str, filename: str) -> YOLO:
    """
    YOLO モデルを Hugging Face からダウンロードして読み込む関数。
    @st.cache_resource デコレータを付けることで、
    「一度ダウンロード・初期化したモデル」をキャッシュし、以降は再利用します。

    Args:
        repo_id (str): Hugging Face 上のリポジトリパス（例: "username/model-name"）
        filename (str): リポジトリ内のモデルファイル名（例: "best.pt"）

    Returns:
        YOLO: 初期化済みの YOLO モデルオブジェクト
    """
    # モデルファイルを認証付きでダウンロード
    model_path = hf_hub_download(
        repo_id=repo_id,
        filename=filename,
        use_auth_token=hf_token
    )
    
    # YOLO モデルを初期化
    model = YOLO(model_path)
    return model

# ────────────
# 3. 実際にモデルをロード（初回だけダウンロード／初期化される）
# ────────────
MODEL_REPO = "username/your-trained-yolo-repo"  # ←自分のリポジトリに書き換えてください
MODEL_FILE = "your_model.pt"                   # ←実際のモデルファイル名に書き換えてください

model = load_yolo_model(repo_id=MODEL_REPO, filename=MODEL_FILE)

# ────────────
# 4. 以降のアプリ内で `model` を使って推論できます
# ────────────
# 例: results = model.predict("path/to/image.jpg")

```
再トレーニングしたモデルをデプロイしたい場合は、Hugging Face上の学習済みモデルファイルを差し替えるだけでOKです。

# 7. Streamlit Community Cloud（SCC）でのデプロイ

## 7.1 GitHub連携
[SCCアカウント作成＆GitHub連携方法はこちら](https://qiita.com/D-SNOW/items/3cbe61fec00cec0c0ec3)

## 7.2 アプリのデプロイ手順
#### 1. Homeの「Create app」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/e0bfb64d-499f-4d25-b62a-f2ecb9a2c947.png)
#### 2. 「Deploy a public app from GitHub」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/1f6bbd4c-6a62-4e2a-a9c1-aed1c2652f00.png)
#### 3. デプロイ対象のリポジトリ・ブランチ・メインファイルパスを指定
空欄をクリックすると、**「Repository」** がプルダウンで表示されるので、デプロイしたいリポジトリを選択してください。
**「Branch」**、**「Main file path」** も同様に選択してください。
**「App URL」** は自動で設定されます。(自分で指定したい場合は自分で設定することも可能)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/1e26eb7f-2a19-4171-97f0-cac6a5d2c439.png)
#### 4. Hugging Faceとの連携設定
:::note info
Streamlitでは、外部に公開したくないAPIキーや認証情報などを安全に管理するために「Secrets」機能が用意されています。
たとえば、Hugging FaceのAPIキーを使用する場合、
以下のように保存して利用します：
:::
画像の「Advanced sttings」をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/da615956-cdf3-4d9a-bdc7-fa991f014297.png)
#### 5. 各種設定を行う
① Pythonのバージョン指定を行いたい場合はこちらで設定
② Hugging Face APIキーはこちらに記述
③ 設定が終わったら「Save」ボタンで保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/02953bfe-1749-40b7-8e03-1123a973be73.png)
#### 6. 最後に「Deploy」ボタン「を押して完了です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/0b4739ea-e26f-433e-9776-e2286db8cfe2.png)


:::note info
## Hugging Faceとの連携設定を後から行う場合
### 1. デプロイしたいアプリの3点リーダーを選択
Streamlit Community Cloud にアクセスし、デプロイしたいアプリの設定を変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/f451cbe1-78f3-4abe-9625-566d0eaab844.png)

### 2. 設定を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/aa40b7c2-f3f0-4e7c-ba6e-90f2092841d3.png)

### 3. 「Secrets」タブを選択し、写真のように設定し、保存する。
黒塗りの部分にご自分のAPIキーを記述してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/d5136bdb-9e77-43d9-bcb2-ca87d9f16bc9.png)
:::

## 7.3 公開・動作確認
外部公開の方法です。自身のアプリを開き、以下の手順に従ってください。
① 「Share」ボタンを押す
② 「Make this app public」を**on**にする
③ 「Copy link」で共有URLを取得できます！！

これを見せたい人に共有して気軽にアプリを外部公開できます！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/a5edc352-bf88-4283-a561-5b54e0d44989.png)

## 7.4 ポケモン図鑑👾アプリ
以下のURLが実際に作った簡単なポケモン図鑑アプリです。
画像をアップロードすることでポケモンを検出できます🔍
アノテーションが大変で「ヒトカゲ」・「リザード」・「リザードン」の3種類しか検出できません^^
色違いは対応していますがメガ進化は対応していません！！！
ぜひ遊んでみてください〜！
https://pokemon-detector-mkywfn9svwca8bpstzg7b5.streamlit.app/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/bdda888a-cb15-4b5f-8182-b373769487bb.png)


# ⚠️エラーが出たら⚠️
#### 1. 右下の「Manage App」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/1e0a7075-8828-4449-b835-7ab73b784223.png)
#### 2. 赤枠のログを参考にデバッグしましょう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/58a5449b-4cb4-4904-a1e6-6ea7ace3714b.png)
#### 3. デバッグを反映させましょう
デバッグが終わったら
① 3点リーダーをクリック
② 「Reboot app」をクリック
これで変更内容が適用されます👍
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4112242/515c856c-1586-4644-aa14-15473911d548.png)

:::

# 最後に
- アプリ公開後も依存パッケージのアップデートなどでエラーが出ることがあります。定期的にアプリの動作確認を推奨します。

- Streamlitアプリを外部公開する際はセキュリティ（SecretsやAPIキーの管理等）にも十分ご注意ください。

- アプリのエラー・質問・ご指摘・「ここを詳しく知りたい」等があれば、ぜひコメントでお知らせください！