news 2026/6/9 23:42:54

使用 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/6/9 22:34:25

W5500多Socket模式下的协议栈资源分配策略详解

W5500多Socket并发实战:14KB缓存怎么分才不翻车? 你有没有遇到过这样的现场: - 网关同时跑Modbus TCP服务器、云平台上传、DNS查询、SSH调试,一切正常; - 某天固件升级包一发,Modbus轮询突然开始丢包,上位机报“连接超时”; - 抓包一看,TCP ACK全到了,但W5500的 …

作者头像 李华
网站建设 2026/6/9 21:17:55

边缘计算在数字孪生同步中的应用解析

边缘计算如何让数字孪生真正“跟得上”物理世界? 在苏州某汽车焊装车间,一台AGV正以1.8m/s高速绕过机械臂——它的路径规划每30ms刷新一次;同一时刻,隔壁变电站里,断路器在检测到短路电流的 4.7毫秒内 完成分闸。这些不是实验室数据,而是真实产线正在发生的控制节拍。 …

作者头像 李华
网站建设 2026/6/9 22:15:24

ModbusTCP协议详解:零基础也能懂的通信模型

Modbus TCP通信模型:从协议报文到产线调试的实战手记 你有没有遇到过这样的场景?HMI画面上某个温度值突然跳变,刷新频率忽快忽慢;Wireshark抓包里看到一连串 0x83 0x02 异常响应,却不知道PLC到底哪根寄存器地址写错了;又或者在STM32上移植完Modbus TCP服务器后,上位机…

作者头像 李华
网站建设 2026/6/9 21:20:15

STM32项目中JLink驱动安装超详细版教程

J-Link驱动&#xff1a;STM32调试链路中被低估的“协议中枢” 你有没有遇到过这样的场景&#xff1f; 刚焊好一块STM32H7最小系统板&#xff0c;J-Link一插上&#xff0c;设备管理器里却只显示一个带黄色感叹号的“Unknown Device”&#xff1b; Keil MDK点下载&#xff0c;弹…

作者头像 李华
网站建设 2026/6/9 22:05:56

一文说清Keil C51与8051内存模型的关系与优化

Keil C51不是“普通C编译器”:它是一把能拧开8051内存架构的精密扳手 你有没有遇到过这样的情况? 写完一段看似干净的C代码,烧进8051芯片后,RAM莫名其妙爆了;中断响应忽快忽慢,示波器上UART波形开始“抽风”;或者更魔幻的——明明只定义了一个 unsigned char flag ,…

作者头像 李华
网站建设 2026/6/5 20:04:32

提高工业设备互操作性:freemodbus系统学习

FreeMODBUS:工业嵌入式通信的“静默引擎”——不靠堆资源,而靠精设计 你有没有遇到过这样的现场调试时刻: PLC主站发来一串0x03读保持寄存器命令,你的MCU却始终没回响; 示波器上明明看到RS-485总线有数据流过,但FreeMODBUS日志里只打印出 MB_EILLSTATE ; 换了一块同…

作者头像 李华