こんちには。
データアナリティクス事業本部 機械学習チームの中村(nokomoro3)です。
今回は、Nginx + OAuth2 Proxy + StreamlitでGoogleログイン後にStreamlitにアクセスする環境をローカルコンテナ環境で作ってみます。
実行環境と準備
実行環境としてはWindows 10マシンを使います。
また前提としてRancher Desktopをセットアップ済みであり、Googleの認証情報作成のためにGoogle Cloudにログインできる環境を作成済みという前提で進めます。
Rancher Desktopのセットアップについては以下も参考にされてください。
Streamlitのコンテナ作成
まずはStreamlit単体のコンテナを作成します。
Dockerfileの作成
以下のようなDockerfileを./streamlit/Dockerfile
に作成しました。
FROM python:3.9-slim
WORKDIR /app
RUN apt-get update && apt-get install -y \
build-essential \
curl \
software-properties-common \
git \
&& rm -rf /var/lib/apt/lists/*
RUN git clone https://github.com/streamlit/streamlit-example.git .
RUN pip3 install -r requirements.txt
EXPOSE 8501
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
ENTRYPOINT ["streamlit", "run", "streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]
以下の公式ドキュメントを参考に作成しています。
docker-compose.ymlの作成
こちらをdocker-composeで立ち上げるために、./docker-compose.yml
を作成します。
version: '3'
services:
streamlit:
container_name: streamlit
build:
context: ./streamlit
dockerfile: Dockerfile
ports:
- 8501:8501
動作確認
docker-composeを使って起動します。
docker compose up -d
localhost:8501
にアクセスすると、以下のような画面を確認できます。
Nginxのリバースプロキシを追加
次にNginxにアクセス後、Streamlitに転送されるような構成をしていきます。
nginx.confの作成
まずは./nginx/nginx.conf
を以下のように記載します。
events {
worker_connections 16;
}
http {
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
location /streamlit/ {
proxy_pass http://streamlit:8501/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
}
何も考えずにproxy_pass
のみの設定を記載すると、WebSocket関連でエラーが出たので以下を参考に設定をしています。
docker-compose.ymlの追記
./docker-compose.yml
にNginxの部分を追記します。
nginx:
container_name: nginx
image: nginx:latest
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- 8000:80
depends_on:
- streamlit
動作確認
再度立ち上げなおします。
docker-compose down
docker-compose up -d
localhost:8000/streamlit
にアクセスすると、先ほどと同じStreamlitの画面を確認できるはずです。
OAuth2 Proxyの導入
OAuth 同意画面の作成
以下に従って、OAuth Providerの設定を行っていきます。
まずは以下にアクセスし使用するプロジェクトを選択します。
- https://console.cloud.google.com
以下のメニューで、「OAuth 同意画面」を作成します。(なお「OAuth 同意画面」はプロジェクトに対して一つ作成する形になりますので、既に存在する場合は流用などをされてください)
User Typeを「内部」とすることで、Google Cloudのプロジェクトと同じ組織内のGoogleアカウントがログインできるようになります。
アプリ名を適当に入力し、メールアドレスを入力します。
デベロッパーの連絡先としてメールアドレスをこちらにも入力します。
以降は特に変更せず進めて「OAuth 同意画面」の作成は完了です。
認証情報の作成
「認証情報」を作成していきます。
「認証情報を作成」を押下し、「OAuth クライアント ID」をクリックします。
「ウェブ アプリケーション」を選択し、適当な名前を入力して押下します。
承認済みのリダイレクトURIに以下を追記して、「作成」を押下します。
こちらのリダイレクトURIは、後程OAuth2 Proxyの設定で使用します。
最後にクライアントIDとクライアントシークレットが表示されますので、控えておきます。
以上で認証情報の設定は完了です。
docker-compose.ymlの追記
docker-compose.yml
にOAuth2 Proxyのコンテナを追加していきます。
oauth2-proxy:
container_name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:latest
ports:
- "4180:4180"
env_file:
- ./oauth2_proxy.env
また、./oauth2_proxy.env
は以下のようにOAuth2 Proxyの設定値を記載しておきます。
OAUTH2_PROXY_PROVIDER=google
OAUTH2_PROXY_CLIENT_ID={作成したクライアントID}
OAUTH2_PROXY_CLIENT_SECRET={作成したクライアントシークレット}
OAUTH2_PROXY_COOKIE_SECRET={パスワードジェネレータなどで作成するランダムな文字列}
OAUTH2_PROXY_REDIRECT_URL={認証情報作成時に記載した承認済みリダイレクトURI}
OAUTH2_PROXY_EMAIL_DOMAINS="*"
OAUTH2_PROXY_HTTP_ADDRESS="0.0.0.0:4180"
OAUTH2_PROXY_COOKIE_SECURE=false
OAUTH2_PROXY_COOKIE_SECRETは自身でパスワードジェネレータなどを使って、ランダムな文字列を作成してください。
nginx.confの修正
最後にNginxからOAuth2 Proxyに転送するよう./nginx/nginx.conf
に設定を追加します。
events {
worker_connections 16;
}
http {
server {
listen 80;
server_name localhost;
location / {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
root /usr/share/nginx/html;
index index.html index.htm;
}
location /streamlit/ {
auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;
proxy_pass http://streamlit:8501/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location = /oauth2/callback {
proxy_pass http://oauth2-proxy:4180;
}
location /oauth2/ {
proxy_pass http://oauth2-proxy:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Auth-Request-Redirect $request_uri;
}
location = /oauth2/auth {
proxy_pass http://oauth2-proxy:4180;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header Content-Length "";
proxy_pass_request_body off;
}
}
}
動作確認
再度立ち上げなおします。
docker-compose down
docker-compose up -d
localhost:8000/streamlit
にアクセスすると、以下のようにOAuth2 Proxyの画面に遷移します。
OAuth 同意画面が表示されますので、アカウントを選択して進みます。
「次へ」を押下して進みます。
すると、streamlitの画面に転送されます。
Nginx側(localhost:8000
)にも認証が必要となるよう設定をしましたが、一度Streamlit側で認証済みであればこちらにもアクセスできるようになります。
補足
最終なdocker-compose.ymlの記載
最終的にはStreamlitもOAuth2 ProxyもNginx経由でアクセスするので、ポートの設定を削除してもOKです。
version: '3'
services:
streamlit:
container_name: streamlit
build:
context: ./streamlit
dockerfile: Dockerfile
nginx:
container_name: nginx
image: nginx:latest
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
ports:
- 8000:80
depends_on:
- streamlit
- oauth2-proxy
oauth2-proxy:
container_name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:latest
env_file:
- ./oauth2_proxy.env
ログインをやり直して動作確認するには
ブラウザの開発ツールのApplicationタブで、StorageのCookiesにhttp://localhost:8000があると思いますので、そちらをClearすれば再度ログインからやり直して動作確認できます。
まとめ
いかがでしたでしょうか。GoogleをIdPとしたログインは組織内部に限定することも可能ですので、社内に限定公開したい場合などに有効に使えそうです。
これらをAWS上にデプロイする方法も今後記事にしたいと思います。本記事が皆様のご参考になれば幸いです。