在Docker中运行Doctr机器学习模型时进程无限挂起问题
问题描述
我开发了一个基于FastAPI的OCR应用,通过Doctr模型实现图片转文本功能。本地执行uvicorn app.main:app --reload时完全正常,但Docker化后进程无限挂起。我使用的是M1 Mac,尝试将模型相关导入移至函数内部仍无法解决问题。
相关代码及配置如下:
初始模型代码
from doctr.io import DocumentFile from doctr.models import ocr_predictor __version__ = "0.1.1" model = ocr_predictor(pretrained=True) def process_image(image_path): document = DocumentFile.from_images(image_path) result = model(document) json_response = result.export() return json_response
FastAPI主文件
from app.model.model import __version__ as model_version from app.model.model import process_image from fastapi import FastAPI, HTTPException, UploadFile app = FastAPI() @app.get("/") def home(): return {"health_check": "OK", "model_version": 'model_version'} # 注:此处应使用变量model_version而非字符串
Dockerfile
FROM tiangolo/uvicorn-gunicorn-fastapi:python3.9 RUN apt-get update RUN apt install -y libgl1-mesa-glx COPY ./requirements.txt /app/requirements.txt RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt COPY ./app /app/app
调整后的模型代码(导入移至函数内)
__version__ = "0.1.1" def process_image(image_path): from doctr.io import DocumentFile from doctr.models import ocr_predictor model = ocr_predictor(pretrained=True) document = DocumentFile.from_images(image_path) result = model(document) json_response = result.export() return json_response
解决方案
1. 适配M1 ARM架构的Docker镜像
M1 Mac采用ARM架构,默认的tiangolo/uvicorn-gunicorn-fastapi:python3.9镜像是x86架构,跨架构运行可能导致Doctr模型加载时死锁或挂起,可通过以下两种方式解决:
方式一:指定平台构建镜像
修改Dockerfile开头,强制使用x86平台兼容模式:
FROM --platform=linux/amd64 tiangolo/uvicorn-gunicorn-fastapi:python3.9
方式二:使用ARM原生基础镜像
改用支持ARM架构的Python基础镜像,自行搭建FastAPI运行环境:
FROM python:3.9-slim # 安装系统依赖 RUN apt-get update && apt-get install -y --no-install-recommends \ libgl1-mesa-glx \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY ./requirements.txt /app/requirements.txt RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt COPY ./app /app/app # 直接用Uvicorn启动服务 CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
2. 优化模型加载逻辑
即使将导入移至函数内,首次调用时下载预训练模型可能因网络或权限问题卡住,可提前下载模型并挂载到容器中:
- 本地运行一次
process_image函数,让Doctr将预训练模型下载到默认缓存路径(通常为~/.cache/doctr)。 - 启动容器时挂载缓存目录:
docker run -p 8000:80 -v ~/.cache/doctr:/root/.cache/doctr your-image-name
也可手动指定本地模型路径(需提前下载权重文件):
def process_image(image_path): import torch from doctr.io import DocumentFile from doctr.models import ocr_predictor # 加载本地权重文件 model = ocr_predictor(pretrained=False, det_arch='db_resnet50', rec_arch='crnn_vgg16_bn') model.detector.load_state_dict(torch.load('/path/to/detector_weights.pth')) model.recognizer.load_state_dict(torch.load('/path/to/recognizer_weights.pth')) document = DocumentFile.from_images(image_path) result = model(document) json_response = result.export() return json_response
3. 调整Web服务进程配置
默认的Gunicorn多worker配置可能与Doctr模型加载冲突,尝试使用单worker运行:
在Dockerfile中添加环境变量:
ENV WEB_CONCURRENCY=1
4. 调试容器运行日志
启动容器时添加交互式参数,查看实时日志定位挂起位置:
docker run -p 8000:80 -it your-image-name
观察日志是否卡在模型下载、初始化或服务启动阶段,针对性解决问题。
内容的提问来源于stack exchange,提问作者Ebrahim Soliman
相关产品推荐
相关产品推荐

