Streamlitはpythonのアプリケーションフレームワークで、簡単にデータの可視化や機械学習モデルのアプリを作成できるて便利。
今回はStreamlitをDocker上で構築して動かしていたのですが、機械学習のDockerイメージはどうしてもイメージサイズがデカくなってしまうのでマルチステージビルドで軽くしちゃおうと思ったら動かなくなりました。というお話。
修正前
requirements.txt
streamlit
plotly
pandas
scikit-learn
FROM python:3.7
USER root
EXPOSE 8501
WORKDIR /streamlit-docker
COPY requirements.txt /streamlit-docker
RUN pip install -r requirements.txt
CMD streamlit run app.py
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN mkdir -p /root/.streamlit
RUN bash -c 'echo -e "\
[general]\n\
email = \"\"\n\
" > /root/.streamlit/credentials.toml'
RUN bash -c 'echo -e "\
[server]\n\
enableCORS = false\n\
" > /root/.streamlit/config.toml'
この状態でもしっかり動くのですが、今回はdockerイメージサイズを減らすために変更しました。
マルチステージビルド
FROM python:3.7-buster as builder
COPY requirements.txt /streamlit-docker
RUN pip install -r requirements.txt
FROM python:3.7-slim-buster as runner
COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages
COPY --from=builder /usr/local/bin/streamlit /usr/local/bin/streamlit
WORKDIR /streamlit-docker
USER root
EXPOSE 8501
CMD streamlit run app.py
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN mkdir -p /root/.streamlit
RUN bash -c 'echo -e "\
[general]\n\
email = \"\"\n\
" > /root/.streamlit/credentials.toml'
RUN bash -c 'echo -e "\
[server]\n\
enableCORS = false\n\
" > /root/.streamlit/config.toml'
pythonのマルチステージビルドは以下の記事を参考にしました。
・Pythonの機械学習用Docker imageのサイズ削減方法の紹介
・仕事でPythonコンテナをデプロイする人向けのDockerfile (1): オールマイティ編
この状態でコンテナを立ち上げるとエラーが出ます。
/bin/sh: 1: streamlit: not found
どこで引っかかってるかというと、Dockerfileのこの部分です。
CMD streamlit run app.py
要するにpathを通せてないよって言われてます。
解決法
streamlitの通すパスを見つけるためにマルチステージビルド前の動くコンテナを使って調べます。
whichコマンドでコマンドのフルパスを表示させます。
>> which streamlit
/usr/local/bin/streamlit
通すパスがわかったので、dockerfileを修正します。
1. ビルドステージから/usr/local/bin/streamlitをコピー
2. ENVコマンドでPATHを通す
これで動きました。
FROM python:3.7-buster as builder
WORKDIR /streamlit-docker
COPY requirements.txt /streamlit-docker
RUN pip install -r requirements.txt
FROM python:3.7-slim-buster as runner
COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.7/site-packages
# 追加
COPY --from=builder /usr/local/bin/streamlit /usr/local/bin/streamlit
ENV PATH $PATH:/usr/local/bin/streamlit
WORKDIR /streamlit-docker
USER root
EXPOSE 8501
CMD streamlit run app.py
ENV LC_ALL=C.UTF-8
ENV LANG=C.UTF-8
RUN mkdir -p /root/.streamlit
RUN bash -c 'echo -e "\
[general]\n\
email = \"\"\n\
" > /root/.streamlit/credentials.toml'
RUN bash -c 'echo -e "\
[server]\n\
enableCORS = false\n\
" > /root/.streamlit/config.toml'