使用 Docker 部署 Streamlit

那么,你有一个很棒的应用,想开始与他人分享,该怎么做呢?你有几种选择。首先,你想在哪里运行 Streamlit 应用,以及如何访问它?

  • 在你的企业网络中 - 大多数企业网络都是对外封闭的。你通常使用 VPN 登录企业网络并访问其中的资源。你可以出于安全原因在企业网络中的服务器上运行 Streamlit 应用,以确保只有公司内部人员可以访问它。
  • 在云中 - 如果你想从企业网络外部访问你的 Streamlit 应用,或者与家庭网络或笔记本电脑外部的人分享你的应用,你可以选择此选项。在这种情况下,这将取决于你的托管提供商。我们有来自 Heroku、AWS 和其他提供商的社区提交指南

无论你决定在哪里部署你的应用,首先都需要对其进行容器化。本指南将引导你使用 Docker 部署应用。如果你偏好 Kubernetes,请参阅使用 Kubernetes 部署 Streamlit

  1. 安装 Docker Engine
  2. 检查网络端口可访问性

如果你还没有安装 Docker,请在服务器上安装。Docker 为许多 Linux 发行版(包括以下发行版)提供了 .deb 和 .rpm

通过运行 hello-world Docker 镜像来验证 Docker Engine 是否正确安装

sudo docker run hello-world
star

提示

按照 Docker 官方的Linux 安装后步骤,以非 root 用户身份运行 Docker,这样你就不必在 docker 命令前加上 sudo

由于你和你的用户都在企业 VPN 后面,你需要确保你们所有人都能访问某个网络端口。假设端口是 8501,因为它是 Streamlit 使用的默认端口。请联系你的 IT 团队,请求为你和你的用户开通端口 8501 的访问权限。

Docker 通过读取 Dockerfile 中的指令来构建镜像。Dockerfile 是一个文本文件,包含用户在命令行中调用以组装镜像的所有命令。在Dockerfile 参考中了解更多信息。docker build 命令从 Dockerfile 构建镜像。docker run 命令首先在指定的镜像上创建一个容器,然后使用指定的命令启动它。

这是一个示例 Dockerfile,你可以将其添加到你的目录根目录中,例如在 /app/

# app/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"]

让我们逐行讲解 Dockerfile

  1. Dockerfile 必须以 FROM 指令开头。它为容器设置基础镜像(可以理解为操作系统)

    FROM python:3.9-slim

    Docker 有许多基于不同 Linux 发行版的官方 Docker 基础镜像。它们还提供包含特定语言模块(例如 Python)的基础镜像。python 镜像有许多变种,每种都针对特定的使用场景。在这里,我们使用 python:3.9-slim 镜像,它是一个轻量级镜像,包含最新版本的 Python 3.9。

    star

    提示

    你也可以使用自己的基础镜像,前提是你使用的镜像包含 Streamlit 支持的 Python 版本。使用任何特定基础镜像都没有通用的方法,也没有官方的 Streamlit 专用基础镜像。

  2.  WORKDIR 指令设置其后在 Dockerfile 中的任何 RUN、 CMD、 ENTRYPOINT、 COPY 和 ADD 指令的工作目录。我们将其设置为 app/

    WORKDIR /app
    priority_high

    重要

    开发流程中所述,对于 Streamlit 1.10.0 及更高版本,Streamlit 应用无法从 Linux 发行版的根目录运行。你的主脚本应该位于根目录以外的目录中。如果你尝试从根目录运行 Streamlit 应用,Streamlit 将抛出 FileNotFoundError: [Errno 2] No such file or directory 错误。有关更多信息,请参阅 GitHub issue #5239

    如果你使用的是 Streamlit 1.10.0 或更高版本,则必须将 WORKDIR 设置为根目录以外的目录。例如,你可以将 WORKDIR 设置为 /app,如上面示例 Dockerfile 所示。

  3. 安装 git,以便我们可以从远程仓库克隆应用代码

    RUN apt-get update && apt-get install -y \ build-essential \ curl \ software-properties-common \ git \ && rm -rf /var/lib/apt/lists/*
  4. 将位于远程仓库中的代码克隆到 WORKDIR

    a. 如果你的代码位于公共仓库中

    RUN git clone https://github.com/streamlit/streamlit-example.git .

    克隆后,WORKDIR 的目录结构如下所示

    app/ - requirements.txt - streamlit_app.py

    其中 requirements.txt 文件包含你的所有Python 依赖项。例如

    altair pandas streamlit

    streamlit_app.py 是你的主脚本。例如

    from collections import namedtuple import altair as alt import math import pandas as pd import streamlit as st """ # Welcome to Streamlit! Edit `/streamlit_app.py` to customize this app to your heart's desire :heart: If you have any questions, checkout our [documentation](https://docs.streamlit.net.cn) and [community forums](https://discuss.streamlit.io). In the meantime, below is an example of what you can do with just a few lines of code: """ with st.echo(code_location='below'): total_points = st.slider("Number of points in spiral", 1, 5000, 2000) num_turns = st.slider("Number of turns in spiral", 1, 100, 9) Point = namedtuple('Point', 'x y') data = [] points_per_turn = total_points / num_turns for curr_point_num in range(total_points): curr_turn, i = divmod(curr_point_num, points_per_turn) angle = (curr_turn + 1) * 2 * math.pi * i / points_per_turn radius = curr_point_num / total_points x = radius * math.cos(angle) y = radius * math.sin(angle) data.append(Point(x, y)) st.altair_chart(alt.Chart(pd.DataFrame(data), height=500, width=500) .mark_circle(color='#0068c9', opacity=0.5) .encode(x='x:Q', y='y:Q'))

    b. 如果你的代码位于私有仓库中,请阅读在构建中使用 SSH 访问私有数据并相应修改 Dockerfile -- 安装 SSH 客户端,下载 github.com 的公钥,然后克隆你的私有仓库。如果你使用替代 VCS(如 GitLab 或 Bitbucket),请查阅该 VCS 的文档,了解如何将代码复制到 Dockerfile 的 WORKDIR 中。

    c. 如果你的代码与 Dockerfile 在同一目录中,则将服务器上的所有应用文件(包括 streamlit_app.pyrequirements.txt 等)复制到容器中,将 git clone 行替换为

    COPY . .

    更一般地,其思想是将你的应用代码从服务器上的任何位置复制到容器中。如果代码不在 Dockerfile 所在的目录中,请修改上面的命令以包含代码路径。

  5. 从容器中克隆的 requirements.txt 安装你的应用Python 依赖项

    RUN pip3 install -r requirements.txt
  6.  EXPOSE 指令通知 Docker 容器在运行时监听指定的网络端口。你的容器需要监听 Streamlit 的(默认)端口 8501

    EXPOSE 8501
  7.  HEALTHCHECK 指令告诉 Docker 如何测试容器以检查它是否仍在工作。你的容器需要监听 Streamlit 的(默认)端口 8501

    HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
  8.  ENTRYPOINT 允许你配置将作为可执行文件运行的容器。在这里,它还包含应用的完整 streamlit run 命令,因此你无需从命令行调用它

    ENTRYPOINT ["streamlit", "run", "streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]

 docker build 命令从 Dockerfile 构建镜像。在服务器的 app/ 目录中运行以下命令来构建镜像

docker build -t streamlit .

-t 标志用于标记镜像。在这里,我们将镜像标记为 streamlit。如果你运行

docker images

你应该在 REPOSITORY 列下看到一个 streamlit 镜像。例如

REPOSITORY TAG IMAGE ID CREATED SIZE streamlit latest 70b0759a094d About a minute ago 1.02GB

现在你已经构建了镜像,可以通过执行以下命令来运行容器

docker run -p 8501:8501 streamlit

-p 标志将容器的端口 8501 发布到你的服务器的 8501 端口。

如果一切顺利,你应该看到类似于以下的输出

docker run -p 8501:8501 streamlit 你现在可以在浏览器中查看你的 Streamlit 应用。URL: http://0.0.0.0:8501

要查看你的应用,用户可以浏览到 http://0.0.0.0:8501http://localhost:8501

push_pin

注意

根据你服务器的网络配置,你可以映射到端口 80/443,以便用户可以使用服务器 IP 或主机名查看你的应用。例如:http://your-server-ip:80http://your-hostname:443

forum

还有其他问题?

我们的 论坛 充满有用的信息和 Streamlit 专家。