项目上使用到了 PaddleOCR,且项目部署环境访问外网需要向安全部门申请添加白名单,流程非常复杂。
直接使用 PaddleOCR 镜像或者通过常规方法构建镜像,在启动容器后运行 PaddleOCR 时,需要联网下载相应的模型。
解决方案是构建一个基础镜像,把需要用到的模型提前下载,内置在基础镜像里。
直接给鱼,Dockerfile 如下:
# 1、构建辅助镜像,用于生成 wheel 文件
FROM python:3.10-slim AS builder
WORKDIR /tmp
# 安装所需的系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends wget build-essential && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# 复制项目依赖文件并生成 wheel 文件
COPY requirements.txt .
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
pip wheel --no-cache-dir --no-deps --wheel-dir /tmp/wheels -r requirements.txt
# 2、构建最终镜像
FROM python:3.10-slim
WORKDIR /tmp
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# 复制从构建阶段生成的文件
COPY --from=builder /tmp/wheels /wheels
COPY --from=builder /tmp/requirements.txt .
# 安装所需的系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends libgl1-mesa-glx libglib2.0-0 libgomp1 && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# 安装依赖
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
pip install --no-cache-dir --find-links /wheels -r requirements.txt && \
rm -rf /wheels
# 下载 OCR 模型文件
RUN python -c "from paddleocr import PaddleOCR, PPStructure;" \
"ocr = PaddleOCR(use_angle_cls=True, lang='ch');" \
"pps = PPStructure(layout=True, show_log=False)"
使用分阶段构建,尽量减小镜像体积。(虽然也 700M+,但见过太多项目镜像动辄几个 G 的——即使没啥功能。)
另外两个环境变量用于优化运行时性能和体验。
PYTHONDONTWRITEBYTECODE
阻止 Python 写 .pyc
文件,以减少磁盘 I/O。PYTHONUNBUFFERED
让 Python 的输出不被缓冲,方便实时查看调试日志。这个就比较简单了,也给一条鱼:
FROM 刚才构建好的基础镜像
WORKDIR /app
# 复制 requirements.txt 并安装依赖
COPY requirements.txt /app/
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
pip install --no-cache-dir -r requirements.txt
# 复制剩余代码
COPY . /app
EXPOSE 8080
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
这里多说一句,为啥把复制操作分开?
因为通常我们的代码变化比较多,而依赖一般比较固定。如果把 COPY . /app
放在前面,那会导致每次更新代码都需要重新安装依赖,比较浪费时间。
(当然,摸鱼的机会可能也少了)
国产替代大背景下,只能申请到 ARM 集群了。在 Intel MacBookPro 下构建的基础镜像,默认是 amd64 架构,推上去之后不能用。
但我们可以指定目标平台 --platform linux/arm64
,构建 ARM 镜像:
docker build --platform linux/arm64 -t app-base:0.1 .
好了,问题解决~
等下,可能还没解决:
54.44 --------------------------------------
54.44 C++ Traceback (most recent call last):
54.44 --------------------------------------
54.44 0 inflateReset2
54.44
54.44 ----------------------
54.44 Error Message Summary:
54.44 ----------------------
54.44 FatalError: Segmentation fault is detected by the operating system.
54.44 [TimeInfo: *** Aborted at 1726242134 (unix time) try "date -d @1726242134" if you are using GNU date ***]
54.44 [SignalInfo: *** SIGSEGV (@0x0) received by PID 8 (TID 0x400000de1020) from PID 0 ***]
54.44
56.10 Segmentation fault (core dumped)
......
ERROR: failed to solve: process "/bin/sh -c python -c \"from paddleocr import PaddleOCR, PPStructure; ocr = PaddleOCR(use_angle_cls=True, lang='ch'); pps = PPStructure(layout=True, show_log=False)\"" did not complete successfully: exit code: 139
大概率是内存不足了,加 8G!
docker build --memory=8g --platform linux/arm64 -t app-base:0.1 .