AWS＋DockerコンテナにおけるStreamlit環境構築

# はじめに

WEBアプリケーションを開発するにあたり、AWSに構築したDockerコンテナ上におけるStreamlitの使い方について調査したのでまとめる。無料枠で構築するのでセキュアなWEBアプリケーションではないことにご注意ください。

セキュアにしたい場合は下記の技術記事を参照ください。

- [ACMでSSLサーバー証明書を発行し、ALBを利用したWebサーバーでHTTPS通信を実現する手順](https://nishinatoshiharu.com/ssl-alb-with-acm/)

次の手順で環境構築の方法を説明する。

- AWS VPCとEC2インスタンスの構築
- Dockerの構築
- StreamlitによるWEBアプリケーションの構築

最終的に構築したい環境は下図の通りである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/5b276b99-6c79-1ebd-450b-b97826396cf1.png)

- [AWS アーキテクチャアイコン](https://aws.amazon.com/jp/architecture/icons/)

# AWS VPCとEC2インスタンスの構築

参照資料をもとに下図のようにAWSのVPCとEC2インスタンスを構築する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/60101413-c5c5-3156-ea25-b0ed0847e4f7.png)

インバウンドルールは下記のように設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/ddb97c7c-ddff-3f22-1977-a88c461c2360.png)


参照資料

- [VPC作成からEC2インスタンス起動まで（その1）](https://dev.classmethod.jp/articles/creation_vpc_ec2_for_beginner_1/)
- [VPC作成からEC2インスタンス起動まで（その2）](https://dev.classmethod.jp/articles/creation_vpc_ec2_for_beginner_2/)
- [Amazon EC2にSSH接続する](https://dev.classmethod.jp/articles/aws-beginner-ec2-ssh/)

# Dockerの構築

Dockerをインストールする。

```
$ sudo yum install -y docker
$ sudo systemctl start docker
$ sudo usermod -a -G docker ec2-user
```

自動起動を有効にする。

```
$ sudo systemctl enable docker
```

docker-composeをインストールする。

```
$ sudo curl -L https://github.com/docker/compose/releases/download/1.28.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
```

参照資料
 
- [Amazon Linux2にDockerをインストールする](https://qiita.com/reoring/items/0d1f556064d363f0ccb8)

# StreamlitによるWEBアプリケーションの構築

コンテナを作成する。ポートの指定は下記の技術記事を参照した。

参照記事

- [Dockerコンテナにネットワークアクセスする](https://qiita.com/ksato9700/items/0b4c7de5d857dc731443)

```
$ docker run -it -p 443:8501 --name stl_hello jupyter/datascience-notebook  /bin/bash
```

app.pyファイルを作成する。

```python
import streamlit as st
st.title("hello")
```

streamlitをインストールし、app.pyを実行する。

```
$ pip3 install streamlit
$ python3 -m streamlit run app.py
```

ターミナル上に下記が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/913ac1dc-5854-2c7b-e15c-bf31b4c9ff2f.png)


ローカルPCのWEBブラウザで開く。
http://EC２インスタンスのIPアドレス:443

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139678/90622f12-513a-3695-912a-822292c98b13.png)


# 補足：Streamlitの常時実行

Streamlitを常時実行するには下記のように実行すればよい。

```
# EC2インスタンスでの実行
$ nohup docker run -it -p 443:8501 --name stl_hello jupyter/datascience-notebook  /bin/bash &
```

```
# Docker containerでの実行
$ nohup python3 -m streamlit run app.py &
```

実行されているか確認するには下記を実行すればよい。

```
$ ps -aux | grep docker
```


参照

- [Xserver(Linux)にPythonプログラムを常時実行](https://gakogako.com/python_xserver/#nohup%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%82%92%E5%B8%B8%E9%A7%90%E3%81%95%E3%81%9B%E3%82%8B)

# 補足：簡易的なStreamlitのユーザー認証


```python
import streamlit as st


def is_authenticated(password):
    return password == "admin"


def generate_login_block():
    block1 = st.empty()
    block2 = st.empty()

    return block1, block2


def clean_blocks(blocks):
    for block in blocks:
        block.empty()


def login(blocks):
    blocks[0].markdown("""
            <style>
                input {
                    -webkit-text-security: disc;
                }
            </style>
        """, unsafe_allow_html=True)

    return blocks[1].text_input('Password')


def main():
    st.header('Hello')
    st.balloons()


login_blocks = generate_login_block()
password = login(login_blocks)

if is_authenticated(password):
    clean_blocks(login_blocks)
    main()
elif password:
    st.info("Please enter a valid password")
```

参照

- [User authentication](https://discuss.streamlit.io/t/user-authentication/612)
- [A secure authentication module to validate user credentials in a Streamlit application.](https://github.com/mkhorasani/Streamlit-Authenticator)
- [Streamlitでログイン機能を実装してみる](https://zenn.dev/lapisuru/articles/3ae6dd82e36c29a27190)
- [Building Multi Page Web App Using Streamlit](https://medium.com/@u.praneel.nihar/building-multi-page-web-app-using-streamlit-7a40d55fa5b4)