news 2026/4/15 5:59:20

使用 FastAPI、Azure 和 Docker 进行模型部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 FastAPI、Azure 和 Docker 进行模型部署

原文:towardsdatascience.com/model-deployment-with-fastapi-azure-and-docker-10e5cfbc1f4f

欢迎来到我MLOps 系列文章的第三篇。在 第一篇文章 中,我们探讨了 Docker 以及它是如何简化应用程序打包的。在 第二篇文章 中,我们使用MLflowAzureDocker管理机器学习模型。现在,在这一部分的第三部分,我们将通过构建一个FastAPI应用程序来整合所有内容,该应用程序在 Azure 上为我们之前存储的模型提供服务。这使我们能够创建一个全球可访问的预测服务!

什么是 API?

API就像一座桥梁。每次你与 Python 中的库交互时,你都在使用它的 API。它是你可以与之交互的应用程序公开部分,而其背后的所有内容都是隐藏的。

API 通常用于与 Web 应用程序通信,并提供一组返回数据的 URL(你发送带有一些参数的请求并得到响应)。最常见的是,数据以 JSON 或 XML 等易于解析的格式返回。这与返回 HTML 的网站不同,HTML 包含用于渲染页面的信息。使用 API,你只得到原始数据。

一些 API 是公开的,而另一些则是私有的。在构建 API 时,你决定要共享哪些数据,如何共享,以及与谁共享。一切由你决定!大多数 API 使用 HTTP 协议进行通信。你可能听说过遵循共同标准的REST API。主要的 HTTP 方法包括:

  • GET:检索数据。

  • POST:提交新数据。

  • PUT:更新现有数据。

  • DELETE:删除数据。

这些方法形成了几乎每个 API 都遵循的CRUD(创建、读取、更新、删除)操作。

如何请求 API?

既然我们已经知道了什么是 API,让我们尝试调用一个。我们将使用猫事实 API,它以 JSON 格式返回随机的猫事实。

API 附带文档,解释了可用的端点和参数。端点是请求数据的地址(URL 中的路径)。阅读文档是必不可少的,因为它可以节省你以后的时间。

这里有一个使用 Python 的requests库调用 Cat Facts API 的/fact端点的快速示例:

importrequests response=requests.get("https://catfact.ninja/fact").json()print(response)

这个有趣的 API 以 JSON 格式返回关于猫的随机事实:

{'fact':'Cats lap liquid from the underside of their tongue, not from the top.','length':69}

使用requests可以帮助你使用 API,但如果你想要构建一个呢?这就是FastAPI发挥作用的地方。它是构建 API 的最佳框架之一。

FastAPI 基础

有许多 Python 框架可以用于构建 API,但在这个教程中,我选择了FastAPI。它是构建 API 中最好和最简单的框架之一,并且它带有许多实用功能,因此您不需要重新发明轮子:

  • Web 服务器:FastAPI 使用 Uvicorn 为您设置网络服务器。

  • 数据验证:它使用 Pydantic 自动验证数据格式。

  • 自动文档:FastAPI 可以自动生成 API 文档,这使得开发者工作变得非常简单。

您的 FastAPI Python 文件的基本结构

当你使用 FastAPI 构建 API 时,你的.py文件将具有特定的结构,看起来像这样:

importuvicornfromfastapiimportFastAPI#### Here you can define some configurations###app=FastAPI()#### Here you define enpoints###if__name__=="__main__":uvicorn.run(app,host="0.0.0.0",port=8000)
  • app = FastAPI():这创建了一个 FastAPI 实例,它将包含您应用程序的所有功能。

  • if name==“main”:这确保了当直接执行此文件而不是将其作为模块导入时,代码块才会运行。

  • uvicorn.run(app, host=“0.0.0.0”, port=8000):这启动了 Uvicorn 网络服务器,指定了主机 IP 和端口。

创建端点

端点是一个 URL,API 用户可以在此处请求或发送数据。我们主要有两种类型:

  1. GET:用于检索数据。

  2. POST:用于发送新数据。

让我们从最简单的可能的GET端点/开始,它将显示一个问候消息:

importuvicornfromfastapiimportFastAPI app=FastAPI()@app.get("/")asyncdefindex():return{"message":"Welcome to the Iris classification API. Use `/predict` to classify a flower."}if__name__=="__main__":uvicorn.run(app,host="0.0.0.0",port=8000)
  • @app.get(“/”):这个装饰器定义了当向/端点发送 GET 请求时,将调用index()函数。

  • async:FastAPI 允许异步操作。异步函数让您更有效地处理请求,尤其是在处理数据库查询等输入/输出任务时。

让我们添加一个POST端点来提交数据:

importuvicornfromfastapiimportFastAPIfrompydanticimportBaseModel app=FastAPI()className(BaseModel):name:str@app.post("/submit")asyncdefsubmit_name(data:Name):return{"message":f"Hello,{data.name}!"}if__name__=="__main__":uvicorn.run(app,host="0.0.0.0",port=8000)
  • 这个POST端点接受用户输入数据。并非所有 API 都接受用户数据,但当他们这样做时,数据需要具有特定的结构,这在Name(BaseModel)类中定义。

使用 Docker 运行 API

为什么使用 Docker?使用 Docker,您不需要在本地机器上安装依赖项。所有内容都在容器中运行,这使得它易于便携和部署。如果您不熟悉 Docker,请查看我之前的文章初学者指南:Docker。

第 1 步:创建一个 Dockerfile

要部署 FastAPI 应用程序,我们首先创建一个 Dockerfile:

# python base image in the container from Docker HubFROM python:3.9-slim RUN apt-get update-y RUN apt-get install nano unzip RUN apt-get install-y python3.10RUN apt install curl-y RUN curl-fsSL https://get.deta.dev/cli.sh|sh# Set the working directoryWORKDIR/app# Copy the current directory contents into the container at /appCOPY./app# Install Python dependencies specified in requirements.txtRUN pip install--no-cache-dir-r requirements.txt# expose the port that uvicorn will run the app onENV PORT=8000EXPOSE8000# execute the command python main.py (in the WORKDIR) to start the app# CMD ["python", "api.py"]CMD["uvicorn","api:app","--host","0.0.0.0","--port","8000"]
  • 这个 Dockerfile 安装所有依赖项,设置工作目录,并使用 Gunicorn 和 Uvicorn 运行应用程序。requirements.txt文件将包含必要的 Python 包,如 FastAPI、Uvicorn 等。

第 2 步:构建和运行 Docker 容器

构建 Docker 镜像:

docker build.-t fastapiserver# if your are on mac, use :# docker build - platform=linux/amd64 -t fastapiserver

运行 Docker 容器:

docker run-it-v"$(pwd):/app"-p8000:8000-e PORT=8000fastapiserver

一旦运行,打开您的浏览器并转到http://0.0.0.0:8000。您应该能看到您的 FastAPI 应用程序正在运行!

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/75d459a33eb8ece3813393b8cce866fe.png

作者

创建一个用于提供 ML 模型的端点

现在,让我们将MLflowFastAPI结合起来,以提供机器学习模型。我们将加载存储在 Azure 中的模型,并创建一个用于进行预测的端点。

到目前为止,你有两个选择:

  1. 你已经遵循了我的上一篇文章,并且你的模型已经序列化并保存在 Azure 中。

  2. 你没有遵循我的上一篇文章。你需要知道的是:我们在 Iris 数据集上训练了一个模型,该模型根据四个特征预测花朵的类型。我们使用MLflow序列化此模型并将其存储在 Azure 中。如果你没有这样做,你可以从这个 GitHub 文件夹下载 model.pkl 文件并将其上传到 Azure Blob 存储。

完成上述步骤后,无论你是处于案例 1 还是案例 2,你都需要检索你的Azure 存储信息,并在以下脚本中替换相关值:

importuvicornimportpandasaspdfromfastapiimportFastAPIfrompydanticimportBaseModelfromazure.storage.blobimportBlobClientimportjoblibimportio# Initialize FastAPIapp=FastAPI()# Define the request body format for predictionsclassPredictionFeatures(BaseModel):sepal_length:floatsepal_width:floatpetal_length:floatpetal_width:float# Global variable to store the loaded modelmodel=None# Download the model from Azure Blob Storage directly into memorydefdownload_model():globalmodel# If you want to follow the tutorial but don't have an azure account, just load the model directly from the local file# model = joblib.load("path_to_your_local_model/model.pkl")blob=BlobClient(account_url="https://<your-storage-account>.blob.core.windows.net/",container_name="<your-container>",blob_name="model.pkl",credential="<your-storage-key>")# Download the model as a stream of bytesstream=io.BytesIO()blob.download_blob().download_to_stream(stream)# Load the model directly from the in-memory streamstream.seek(0)model=joblib.load(stream)print("Model loaded from Azure Blob Storage successfully!")# Download the model immediately when the script runsdownload_model()# API Root endpoint@app.get("/")asyncdefindex():return{"message":"Welcome to the Iris classification API. Use `/predict` to classify a flower."}# Prediction endpoint@app.post("/predict")asyncdefpredict(features:PredictionFeatures):# Create input DataFrame for predictioninput_data=pd.DataFrame([{"sepal length (cm)":features.sepal_length,"sepal width (cm)":features.sepal_width,"petal length (cm)":features.petal_length,"petal width (cm)":features.petal_width}])# Predict using the loaded modelprediction=model.predict(input_data)# Get the class number (0, 1, or 2)class_index=int(prediction[0])# Get the class name from the class indexclass_names=['setosa','versicolor','virginica']class_name=class_names[class_index]return{"prediction":class_index,"class_name":class_name}if__name__=="__main__":uvicorn.run(app,host="0.0.0.0",port=8000)
  • download_model()函数从 Azure Blob 存储检索模型并将其加载到内存中。

  • 根端点/提供了一个欢迎信息。

  • /predict端点仍然存在,允许用户将花朵测量值作为 JSON 数据发送给模型以获取预测。

  • 在此脚本中,class用于定义用户必须发送到/predict端点的数据结构。在 FastAPI 中这很重要,因为它有助于验证用于预测的传入数据。

本地测试 API

重新构建并运行你的 Docker 容器,然后访问http://0.0.0.0:8000。使用以下 Python 脚本测试预测端点:

importrequests# Define the API endpointurl="http://0.0.0.0:8000/predict"# Define the input datadata={"sepal_length":5.1,"sepal_width":3.5,"petal_length":1.4,"petal_width":0.2}# Make a POST request to the APIresponse=requests.post(url,json=data)# Check if the request was successfulifresponse.status_code==200:# Print the prediction resultprediction=response.json()print("Prediction:",prediction)else:print(f"Failed to get a prediction. Status code:{response.status_code}")print("Response:",response.text)

这将根据输入数据返回预测的花朵分类。我们的花朵属于类别 0,即**-setosa**。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/53c964fe87ce680fef3ca406a386f45a.png

作者

这听起来不错,但这里有个问题:我们的 API 目前仅在本地上可用。如果有人在世界另一端想要用它来预测他们花朵的分类怎么办?你猜对了——我们需要将这个 API 部署到云端。让我们将其部署到 Azure,这样全世界的花迷都可以使用它!

将 FastAPI 部署到 Azure

在开始之前,确保你准备好了订阅 ID和其他相关细节。你可以从 Azure 门户中获取这些信息。接下来,从我的 GitHub克隆必要的文件,并更新deploy.sh脚本。

更新完信息后,只需运行deploy.sh脚本即可自动化整个设置过程。虽然 Azure 提供了图形界面来设置资源,但此脚本通过单个命令简化了所有操作。

下面是运行deploy.sh脚本时你正在做的事情的分解:

1. 登录并设置订阅:首先,登录到你的 Azure 账户,并设置资源部署的订阅。

az login az accountset--subscription $SUBSCRIPTION_ID

2. 创建资源组:此组将组织您为 FastAPI 部署的所有资源。如果您已经有了资源组,您可以跳过此步骤或在脚本中将其注释掉。

az group create--name $RG_NAME--location<location>

3. 将 Docker 镜像推送到 Azure 容器注册库(ACR):在推送 Docker 镜像之前,获取您的 ACR 凭证并登录。

export ACR_USERNAME=$(az acr credential show--name $ACR_NAME--query"username"--output tsv)export ACR_PASSWORD=$(az acr credential show--name $ACR_NAME--query"passwords[0].value"--output tsv)docker login $ACR_NAME.azurecr.io--username"$ACR_USERNAME"--password"$ACR_PASSWORD"
# Push the imagesdocker tag $DOCKER_IMAGE_NAME $ACR_NAME.azurecr.io/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG docker push $ACR_NAME.azurecr.io/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG

4. 创建应用服务计划:设置应用服务计划以在 Azure 上托管您的 FastAPI 服务器。

az appservice plan create--name $ASP_NAME--resource-group $RG_NAME--sku B1--is-linux--location $RG_LOCATION

5. 使用 FastAPI 容器部署 Web 应用:将 ACR 中的 Docker 镜像部署到您的 Web 应用。

az webapp create--resource-group $RG_NAME--plan $ASP_NAME--name $WEB_APP_NAME--deployment-container-image-name $ACR_NAME.azurecr.io/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG

6. 配置 Web 应用以使用容器注册库:设置应用以拉取 Docker 镜像,并配置环境变量。

az webapp config containerset--name $WEB_APP_NAME--resource-group $RG_NAME--docker-custom-image-name $ACR_NAME.azurecr.io/$DOCKER_IMAGE_NAME:$DOCKER_IMAGE_TAG--docker-registry-server-url https://$ACR_NAME.azurecr.io--docker-registry-server-user $ACR_USERNAME--docker-registry-server-password $ACR_PASSWORD--enable-app-service-storage true az webapp config appsettingsset--resource-group $RG_NAME--name $WEB_APP_NAME--settings WEBSITES_PORT=$MLFLOW_PORT

部署脚本完成后,检查 Azure 门户以确认您的 API 已上线并可访问。导航到应用服务以获取您已部署的 FastAPI Web 应用的 URL。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8c966f99f35170c776009b733e99bb71.png

作者提供

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4c8a178092a258b06a0bcdef87396656.png

作者提供

恭喜!您的 API 现在已上线,世界上任何地方的人都可以使用它来根据特征对花卉进行分类。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/76bd57ed40adc12bc7aa156f4ebee49f.png

作者提供

最终测试:访问已部署的 API

让我们使用与之前相同的 Python 请求脚本来测试已部署的 API,但这次将本地 URL 替换为 Azure 的实际 URL。您应该能看到返回的预测结果!

结论

这篇文章到此结束。您已成功将 FastAPI 应用部署到 Azure,并且它准备好为任何拥有花卉数据的人提供服务。在本系列的下一部分,我们将通过添加文档、单元测试,以及使用CI/CDGitHub Actions自动化部署来改进 API。敬请期待!

感谢您的阅读!

***注意:*某些部分的文章最初是用法语撰写的,并在 ChatGPT 的帮助下翻译成英语。

如果您觉得这篇文章信息丰富且有帮助,请毫不犹豫地👏并关注我在Medium | LinkedIn上的账号。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 19:26:26

ESP32 GPIO输出频率限制剖析:深度讲解性能边界

ESP32 GPIO高频输出实战手记&#xff1a;从“为什么翻不过5 MHz”到稳定输出40 MHz方波 你有没有试过在ESP32上用 gpio_set_level() 循环翻转一个引脚&#xff0c;满怀期待地把示波器探头接上去——结果只看到模糊抖动的1.2 MHz方波&#xff1f;而手册里清清楚楚写着“GPIO可…

作者头像 李华
网站建设 2026/4/6 1:15:07

USB3.0高速差分对布线:手把手教程(90Ω阻抗)

USB3.0高速差分对布线&#xff1a;90Ω不是目标&#xff0c;而是生存底线你有没有遇到过这样的场景&#xff1f;一块工业相机主板&#xff0c;硬件全通电、FPGA配置成功、USB3.0 PHY时钟锁定&#xff0c;但插上电脑后设备管理器里始终不出现“SuperSpeed USB Device”——只在系…

作者头像 李华
网站建设 2026/4/4 20:49:05

CCS安装教程实战案例:从下载到运行完整流程

CCS安装不是点下一步&#xff1a;一个C2000工程师的环境构建手记 上周五下午四点十七分&#xff0c;我第7次拔掉XDS110探针&#xff0c;盯着CCS里那行红色报错发呆&#xff1a;“Error connecting to the target: (Error -260 0x0)”。不是驱动没装&#xff0c;不是USB接触不良…

作者头像 李华
网站建设 2026/4/12 1:24:08

新手教程:如何用profile API诊断慢搜索请求

用 Profile API 解剖一次慢搜索:从耗时数字到索引设计的实战推演 你有没有遇到过这样的情况:线上监控突然报警,商品搜索 P99 延迟从 80ms 跳到 1.7s;Kibana 查看 search.fetch_time 指标飙升,但 query_total 并没明显增长;重启协调节点无效,扩容数据节点后延迟反而…

作者头像 李华
网站建设 2026/4/4 6:56:19

MTools开箱体验:比ChatGPT更专注的文本处理工具

MTools开箱体验&#xff1a;比ChatGPT更专注的文本处理工具 1. 为什么你需要一个“不聊天”的AI工具&#xff1f; 你有没有过这样的经历&#xff1a;打开ChatGPT&#xff0c;想快速总结一篇长邮件&#xff0c;结果它先热情地问候你&#xff0c;再问你想总结哪类内容&#xff…

作者头像 李华