云服务器上部署YOLOv5推理服务:从环境配置到FastAPI接口上线全指南

发布时间:2026/10/22 11:01:48
云服务器上部署YOLOv5推理服务:从环境配置到FastAPI接口上线全指南
自己在模型推理上折腾过不少项目从最开始在本地笔记本上跑检测程序到后来把模型搬到云服务器上做线上服务中间踩过的坑比想象中多。YOLOv5这类单阶段目标检测模型训练倒还好说真正麻烦的是“怎么部署到一台空荡荡的云服务器上”。很多第一次接触云 GPU 机型的同学买机器之前信心满满结果连显卡驱动都装不对最终模型根本跑不起来。这篇笔记就是把“在云服务器上部署 YOLOv5 模型”的整体过程完整写下来从选机器、装环境、跑通推理脚本到把模型包装成一个 HTTP 接口再到线上问题排查和性能调优全部覆盖。你可以直接把它当作一份操作手册来用每一步我都尽量写清楚为什么这么做以及有哪些坑需要注意。适合刚租到 GPU 服务器、想快速上线一个目标检测服务的同学参考。1. 部署前先搞清楚模型要住在哪台机器上很多人部署失败的根源不是技术而是机器选型时就出了问题。YOLOv5 对训练和推理的资源需求差异很大如果你只是想把一个训练好的权重文件变成接口服务几十块钱一小时的顶级显卡完全没必要。先把需求拆清楚再决定买什么机器。1.1 GPU 实例与纯 CPU 实例到底差在哪先给一个直观对比。同样跑 YOLOv5s 模型输入尺寸 640x640单张图片推理纯 CPU 实例几核几G内存大概需要 300~800 毫秒而且一旦多个请求同时进来延迟会迅速恶化入门级 GPU 实例类似 T4、L4、A10 级别的加速卡单张图片大约 10~30 毫秒批量处理时吞吐量还能再拉高好几倍。单看数值有点抽象换个说法CPU 推理勉强能应付“偶尔查一张图”的内部小工具但扛不住真实的线上请求量。比如一个智能相册服务用户上传图片后希望在 1 秒内看到检测框CPU 方案很容易超时而 GPU 方案不仅单张快还能同时处理多个请求。所以凡是打算做成在线服务的 YOLOv5 模型优先用带 GPU 的实例不要为了省那点钱去赌 CPU 性能。1.2 按推理场景选显存别照着训练标准买显存大小是选型时最关键的参数但很多人会拿训练时的显存需求来套推理场景结果买大了。YOLOv5 推理时的显存占用主要由几个因素决定模型本身参数规模YOLOv5s 大约需要 2~3GB 显存YOLOv5x 可能需要 8GB 以上推理输入尺寸图片越大、中间特征图越大占用越高是否开半精度FP16开半精度后显存占用会明显降低是否同时加载多个模型或者开了多进程推理。我个人的建议是如果只是跑 YOLOv5s 或者 YOLOv5m单人单模型做在线推理选 8GB~16GB 显存的实例就够用如果还想顺便做模型微调或者后期要集成多个模型再考虑 24GB 以上的卡。云厂商在购买页面里通常会写清楚具体显卡型号和显存大小直接按这个标准筛就行。1.3 操作系统、快照与基础初始化云服务器买回来之后第一步不是急着装环境而是先做好三件基础工作操作系统选择。建议使用 Ubuntu 20.04 或 22.04。这两个版本对深度学习依赖的兼容性最好教程也最多遇到问题很容易查到。不要为了尝鲜装太新的版本也不要装桌面版服务器版足够用磁盘快照。在还没开始安装任何环境之前先做一个磁盘快照。后面不管你装驱动翻了车、还是把系统搞到无法启动都能靠快照秒级回滚不用重新部署更新系统包。执行一遍apt update apt upgrade把基础软件包刷新到当前版本避免后续安装依赖时因为索引过旧而失败。注意所有重要操作前都做好快照特别是刚拿到机器、即将安装显卡驱动的那一步。这个习惯能帮你省下大把返工时间。2. 环境搭建驱动、CUDA、PyTorch 一个都不能少环境搭建是整个部署过程里最劝退新人的环节。很多同学第一步装显卡驱动时就卡住了后面全程处于“看着教程怀疑人生”的状态。这里我按依赖关系理一遍尽量让你少走弯路。2.1 先搞清楚组件之间的依赖逻辑YOLOv5 本身是一个基于 PyTorch 的检测框架PyTorch 需要调用 CUDA 的运行时接口而 CUDA 运行时又依赖底层显卡驱动。它们的关系是层层向上的依赖链显卡驱动操作系统和硬件之间的桥梁负责最底层的管理和调度CUDA 运行时提供深度学习框架所依赖的并行计算接口PyTorch在 CUDA 运行时之上做张量计算和模型推理YOLOv5在 PyTorch 之上组织网络结构和检测逻辑。很多人混淆的一点是CUDA 并不是通过pip install cuda就能装完的。PyTorch 安装包通常会自带一份它所需的 CUDA 运行时组件所以最关键的其实是保证底层显卡驱动足够新否则 PyTorch 会报“CUDA unavailable”或者“driver version is too old”一类的错误。2.2 安装显卡驱动的正确姿势拿到新机器后先执行下面的命令确认当前状态sudo apt update sudo apt install ubuntu-drivers-common ubuntu-drivers devicesubuntu-drivers devices会列出当前机器上可用的驱动版本。如果有系统推荐的版本一般直接执行sudo apt install nvidia-driver-535 sudo reboot重启之后执行nvidia-smi如果能看到类似下面的表格输出说明驱动层已经通了nvidia-smi显示出的显卡型号、驱动版本、显存容量、当前功耗这些信息是后面排查问题的重要依据。提示如果系统提示 nouveau 模块冲突说明开源驱动和闭源驱动在打架。这种情况下先把 nouveau 加入屏蔽列表重新生成启动镜像再重启。不同系统写法略有差异搜索“nouveau 屏蔽”就能找到对应做法这里不展开细写。2.3 创建虚拟环境并安装 YOLOv5 依赖驱动装好之后接下来是安装 Python 环境和 YOLOv5 的依赖。为了保证项目独立我强烈建议建一个虚拟环境不要直接装在系统 Python 里sudo apt install python3-pip python3-venv mkdir -p ~/app cd ~/app python3 -m venv venv source venv/bin/activate然后拉取 YOLOv5 的官方源码并安装依赖git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt如果你对版本敏感建议先固定 PyTorch 版本再安装其他依赖。我的习惯是分成两步pip install torch2.1.* torchvision0.16.* --index-url https://download.pytorch.org/whl/cu121 pip install -r requirements.txt先装好和 CUDA 匹配的 PyTorch再让它去解析 YOLOv5 的其他依赖这样能避免版本之间互相踩踏。如果你服务器带宽一般下载时间会比较长耐心等就行。2.4 快速验证 GPU 是否真的被 PyTorch 识别环境装完别急着跑模型。先用一行 Python 代码确认 PyTorch 能不能正常调用 GPUpython -c import torch; print(torch.cuda.is_available(), torch.cuda.get_device_name(0))如果输出是True加上显卡型号说明 GPU 链路已经打通。如果输出是False大概率是下面三个原因之一显卡驱动没装好nvidia-smi都执行失败驱动版本太旧不满足 PyTorch 对应 CUDA 版本的要求安装 PyTorch 时选了 CPU 版本需要重装成 CUDA 版本。这一步是后面一切推理的基础务必确认通过再继续。3. 跑通模型推理detect.py 与权重文件管理环境就绪之后先别急着写接口把模型推理脚本跑通再做服务化。YOLOv5 官方仓库自带的detect.py就是最好的验证工具。3.1 获取预训练权重或准备自己的权重如果你只是先验证流程YOLOv5 官方仓库的yolov5s.pt是最省事的默认权重。它会自动从官网下载到当前目录。训练过自定义数据的同学需要把自己训练产生的best.pt上传到服务器放在一个固定目录里管理。我一般会建一个weights目录把所有权重文件集中放~/app/yolov5/weights/ yolov5s.pt best.pt ...这样后面写接口代码时路径管理会清晰很多。不要把权重文件散落在多个目录否则排查问题时非常痛苦。3.2 用一条命令跑通文件夹推理进入 YOLOv5 源码目录执行python detect.py --weights weights/yolov5s.pt --source data/images --device 0其中--source可以是一个图片路径也可以是一个文件夹。运行结束后预测结果会保存在runs/detect/exp目录里包括带框图片和检测日志。看到这里说明最基本的推理链路已经通了。3.3 推理参数里的几个关键旋钮detect.py的参数很多但线上部署的时候最常用的就是这几个参数作用实际影响--conf-thres置信度阈值设置过高会漏检过低会产生大量误检常用 0.25~0.5--iou-thresNMS 的 IOU 阈值控制重叠框的合并程度一般保持 0.45 默认值即可--img-size推理输入尺寸越大精度越高但越慢常用 640 或者 1280--device指定设备0表示第一块 GPUcpu表示 CPU 推理--classes只检测指定类别能明显减少后处理耗时如果你是做视频流场景经常会有“同一个目标相邻几帧反复出现”的问题可以在业务侧做去重或者在检测逻辑里把连续帧的检测结果做一次合并。YOLOv5 本身不关心这个问题需要上层自己处理。3.4 快速验证推理速度上线之前最好做一次简单的压测摸底time python detect.py --weights weights/yolov5s.pt --source test_images --device 0 --img-size 640time命令会给出总耗时你再用图片数量算一下平均单张耗时记录下来。这个数字就是你服务化的性能基线后面做优化时对比全靠它。4. 把模型包装成 HTTP 推理服务如果只是自己偶尔用一下跑通脚本就够了。但部署到云服务器的真实需求通常是把模型变成一个可供其他系统调用的接口。这里我用 FastAPI 写一个最小可用的推理服务。4.1 编写最简推理接口先安装服务依赖pip install fastapi uvicorn python-multipart然后在 YOLOv5 项目目录下新建一个api.py代码可以这样写import io import torch from PIL import Image from fastapi import FastAPI, UploadFile, File app FastAPI() model torch.hub.load(ultralytics/yolov5, custom, pathweights/yolov5s.pt, force_reloadFalse) model.conf 0.35 model.iou 0.45 model.agnostic False if torch.cuda.is_available(): model.cuda() app.post(/predict) async def predict(file: UploadFile File(...)): image_bytes await file.read() img Image.open(io.BytesIO(image_bytes)).convert(RGB) results model(img, size640) data results.pandas().xyxy[0] boxes data.to_dict(orientrecords) return {count: len(boxes), results: boxes}这里有几个细节解释一下torch.hub.load的第二个参数custom表示加载本地自定义权重model.conf和model.iou是直接在模型实例上设置阈值效果等同于detect.py里的--conf-thres和--iou-thres代码前面先判断torch.cuda.is_available()这样可以保证在没有 GPU 的环境下也能以 CPU 模式启动调试不至于一运行就崩溃UploadFile接收的是前端上传的原始图片转成 PIL Image 再做推理这是最通用的传图方式。4.2 一张图片是传 Base64 还是传文件接口设计时很多人纠结客户端传 Base64 还是直接传 multipart 文件。两种方式我都用过说下感受multipart 文件上传实现简单FastAPI 里直接一个UploadFile就能接收适合前端页面表单上传、小程序上传等场景Base64 字符串适合 JSON 协议统一的系统间调用尤其当上游服务已经把图片转成 Base64 时直接放在 JSON 字段里传过来会更顺。我个人建议优先支持 multipart因为不需要额外处理字符串解码同时流量开销也更小。如果确定要 Base64记得在服务端做好文件大小限制避免超大图片把服务器内存打爆。4.3 并发请求上来后会发生什么上面这个极简接口有一个隐藏问题默认情况下 FastAPI 的接口是同步阻塞的模型推理代码会占住当前进程一个请求没处理完下一个请求就得等着。如果只是内部小流量调用问题不大一旦请求量大起来响应时间会越来越长。要改善这个问题常见思路有三条用run_in_executor把推理放到线程池里执行但 GPU 推理本身会串行线程池改善的主要是接口层的阻塞把同步接口改成异步任务队列请求先入队处理完再回调适合不理解实时性的场景一次推理处理一批图片也就是动态 batch将多个请求聚合到同一个批次里推理吞吐量提升最明显。对于刚上线的服务我建议先用最基础的同步接口跑起来压测觉得不够再逐步优化。不要一开始就上复杂架构排查问题会非常累。4.4 启动服务并做一次真实调用启动服务uvicorn api:app --host 0.0.0.0 --port 8000--host 0.0.0.0表示监听所有网卡地址这样才能从外部访问到。本地先测试一下curl -X POST -F filetest.jpg http://127.0.0.1:8000/predict如果一切正常会返回类似这样的 JSON{ count: 2, results: [ { xmin: 120.5, ymin: 89.2, xmax: 310.8, ymax: 400.1, confidence: 0.92, class: 0, name: person } ] }到了这一步模型已经变成一个可调用的在线接口了。公网访问还没通的话先去云平台的控制台看安全组规则确认 8000 端口已经放行。5. 上线后的维护systemd 托管与问题排查接口能访问只是部署成功的第一步。真正常态运行没那么容易我把线上最常见的坑整理出来顺便说一下怎么把服务守护住。5.1 用 systemd 让服务在后台常驻直接通过终端跑uvicorn一旦 SSH 断开服务就跟着断了。实际部署时推荐用 systemd 把服务托管起来。新建一个服务文件/etc/systemd/system/yolov5-api.service[Unit] DescriptionYOLOv5 API Service Afternetwork.target [Service] Userubuntu WorkingDirectory/home/ubuntu/app/yolov5 ExecStart/home/ubuntu/app/venv/bin/uvicorn api:app --host 0.0.0.0 --port 8000 Restartalways RestartSec3 [Install] WantedBymulti-user.target依次执行sudo systemctl daemon-reload sudo systemctl enable yolov5-api sudo systemctl start yolov5-api sudo systemctl status yolov5-api之后服务会自动启动进程崩溃也会自动拉起大大减少人工介入。5.2 常见问题排查速查表下面这张表我建议收藏一下都是实际运行中遇到最高频的问题问题现象可能原因排查思路接口报 504 或超时推理耗时太长或请求堆积查日志看平均响应时间适当降低输入尺寸显存不足报错输入图片过大、并发进程过多缩小图片、关闭多余进程、换更大显存的实例外部访问不通安全组没放行端口检查云平台的安全组规则和本地防火墙启动时 CUDA 报错驱动版本与 PyTorch 版本不匹配执行nvidia-smi确认驱动再选匹配的 PyTorch推理结果一直为空置信度阈值太高或类别不对先调低conf到 0.1 观察输出中文路径或中文文件名报错PyTorch 与底层语言环境编码不一致全部改成英文路径、英文文件名5.3 推理结果不对阈值调参经验部署时最困扰的往往是“模型跑起来了但框不对”。调试时我习惯先把置信度阈值降下来看结果conf0.1看到尽可能多的检测框确认模型到底检出了什么conf0.25一般场景的默认推荐值误检不多、漏检可控conf0.5只在目标特别明显时保留结果适合对准确率要求很高、不能接受误报的场景。注意 IOU 阈值不要随便动。它控制的是“重叠框去重”的严格程度默认 0.45 在多数场景都适用。调得过高会导致同一个目标出现多个框。5.4 推理性能的进一步优化方向如果你测下来吞吐不满意可以从简单到复杂逐个尝试开启半精度推理在接口代码里加上model.half()要求输入图片也转成 FP16通常能带来一截明显的加速降低输入尺寸从 640 降到 480 或 416精度会略有损失但速度提升明显做动态 batch把多个请求攒在一起推理GPU 利用率能大幅提高尝试用 TensorRT 对模型做加速这是能推到极限的方案但工程复杂度也最高。这里特别提醒做性能优化时一次只改一个变量改完重新压测记录数据不要同时改好几个参数。否则你根本分不清到底哪一步带来了提升。6. 最后分享几则压箱底的部署心得整个过程走下来我最大的感受是部署 YOLOv5 本身难度不大难的是各种细枝末节的环境问题。以下几条是我踩过较多次坑之后沉淀下来的做法直接分享给你第一机器拿到手先做快照装好驱动再做一次快照。环境一旦弄坏回滚比重装快得多第二所有文件路径尽量用英文不要用带空格或中文的目录名能避开大量意想不到的报错第三把requirements.txt和 PyTorch 版本记录保留好之后在另一台机器上重建环境时可以节省不少时间第四不要一上来就追求高并发先把单请求链路跑通再根据压测结果做 batch 或换更高效的推理引擎。还有一件常被忽略的事模型接口上线后日志一定要记录请求来源、图片大小、推理耗时、检测结果数量。出了问题查日志远比对着控制台干瞪眼有效。这一套流程跑通之后再往后接视频流、集成到业务系统或者换 YOLOv8底层的部署思路都是一样的。