- scheduler: ffmpeg 异步线程 + GPU 串行调度 + 模型复用(2N→2 次加载) - pipeline: 阶段拆分(extract/asr/translate),中间数据存 Task 字段 - translate_service: 长度排序批处理,padding 浪费减少 91% - model_manager: ASR/翻译不共驻,BatchedInferencePipeline 批量解码 - 日志分级: INFO=任务流转里程碑,DEBUG=进度详情;默认 INFO - 前端: 日志最新在上+滚动感知+退避轮询;24h 时间;上传中状态显示 - /health: 返回完整 Whisper/NLLB 配置 - upload_service: 单事务 complete + 扩展名白名单 - task_router: 合并 UploadSession 虚拟任务到列表 - Dockerfile: CPU/GPU 独立构建链,deps 缓存稳定 - prefetch_models: 安装时预下载模型权重
125 lines
7.0 KiB
Docker
125 lines
7.0 KiB
Docker
# syntax=docker/dockerfile:1.7
|
||
# audio2text — 一份 Dockerfile,CPU(dev) / GPU(prod) 双形态。
|
||
# docker build --build-arg VARIANT=cpu -t audio2text:cpu .
|
||
# docker build --build-arg VARIANT=gpu -t audio2text:gpu .
|
||
# docker compose --profile dev up -d --build # 开发:dev target + 源码挂载 + reload
|
||
#
|
||
# 分层目标:依赖层(deps)稳定固化,代码层(final/dev)在最末,改代码不重装依赖。
|
||
# BuildKit 缓存挂载(--mount=type=cache):pip wheel 跨构建复用,二次构建秒级。
|
||
#
|
||
# 安全约束:PyTorch CPU wheel 与 GPU(CUDA) wheel 是两个不兼容二进制包。
|
||
# - CPU 版 torch.cuda.is_available()=False(CPU 预期)
|
||
# - GPU 版 torch.cuda.is_available()=True(GPU 可调度)
|
||
# 因此 torch 必须按 VARIANT 分叉装不同 wheel,绝不能跨 variant 共享依赖层。
|
||
# deps 阶段用 FROM base-${VARIANT},CPU/GPU 是两条独立构建链,各自装对应 torch。
|
||
|
||
ARG VARIANT=cpu
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 1. 基础镜像分叉:CPU 用 slim Python,GPU 用 CUDA runtime + 手动装 python3.12
|
||
# ---------------------------------------------------------------------------
|
||
FROM python:3.12-slim AS base-cpu
|
||
|
||
FROM nvidia/cuda:12.1.0-runtime-ubuntu22.04 AS base-gpu
|
||
# Ubuntu 22.04 默认源只有 python3.10/3.11,需加 deadsnakes PPA 才能装 python3.12。
|
||
# 注意:不能用 python3-pip(那是 3.10 的系统 pip,会把包装到 3.10 site-packages)。
|
||
# 用 python3.12 -m ensurepip 给 3.12 装 pip,确保所有包进 3.12 目录。
|
||
# DEBIAN_FRONTEND=noninteractive 避免 tzdata 等包进入交互式配置卡住构建。
|
||
ENV DEBIAN_FRONTEND=noninteractive
|
||
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
||
software-properties-common gnupg ca-certificates \
|
||
&& add-apt-repository -y ppa:deadsnakes/ppa \
|
||
&& apt-get update -y && apt-get install -y --no-install-recommends \
|
||
python3.12 python3.12-venv python3.12-dev \
|
||
&& rm -rf /var/lib/apt/lists/* \
|
||
&& ln -sf /usr/bin/python3.12 /usr/local/bin/python3 \
|
||
&& ln -sf /usr/bin/python3.12 /usr/local/bin/python \
|
||
&& python3 -m ensurepip \
|
||
&& python3 -m pip install --upgrade pip
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2. deps:系统依赖 + Python 依赖(含 torch)。CPU/GPU 各自一条独立链。
|
||
# final / dev 都 FROM deps,继承对应 variant 的 torch,不串。
|
||
# ---------------------------------------------------------------------------
|
||
FROM base-${VARIANT} AS deps
|
||
ARG VARIANT
|
||
ENV PYTHONUNBUFFERED=1 \
|
||
PIP_NO_CACHE_DIR=1 \
|
||
HF_HOME=/models/huggingface \
|
||
CT2_CACHE=/models/ctranslate2
|
||
|
||
# ffmpeg 是核心系统依赖;patchelf 用于修复 ctranslate2 可执行栈
|
||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||
apt-get update -y && apt-get install -y --no-install-recommends \
|
||
ffmpeg ca-certificates patchelf \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
|
||
WORKDIR /app
|
||
COPY requirements.txt /app/requirements.txt
|
||
|
||
# 【顺序关键】必须先装 torch(按 VARIANT 分叉),再装 requirements。
|
||
# 原因:requirements 里的 transformers / accelerate 依赖 torch,若先装 requirements,
|
||
# pip 会从默认 PyPI 拉来 GPU 版 torch + nvidia-* 全家桶(~2GB),即使后续覆盖装 CPU torch,
|
||
# 那些无用的 nvidia 包仍残留在镜像里。先装 torch 让 pip 解析 requirements 时 torch 已满足。
|
||
#
|
||
# CPU 走 cpu index(~200MB,无 nvidia 依赖);GPU 走默认 PyPI(带 CUDA,~2.5GB)。
|
||
# 两套 wheel 二进制不兼容:CPU 版 cuda.is_available()=False,GPU 版 =True。不可共享。
|
||
RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \
|
||
pip install --upgrade pip && \
|
||
if [ "$VARIANT" = "cpu" ]; then \
|
||
pip install torch --index-url https://download.pytorch.org/whl/cpu ; \
|
||
else \
|
||
pip install torch ; \
|
||
fi
|
||
|
||
# torch 已就位,requirements 里的 transformers/accelerate 解析时复用已装 torch,不重复拉
|
||
RUN --mount=type=cache,target=/root/.cache/pip,sharing=locked \
|
||
pip install -r /app/requirements.txt
|
||
|
||
# ctranslate2 的 .so 带可执行栈标志(PT_GNU_STACK X),在某些内核 + Docker 组合下
|
||
# 会触发 "cannot enable executable stack as shared object requires"。用 patchelf
|
||
# 清掉该标志(改为 RW),无需放宽容器安全策略。
|
||
# 注意:库在 ctranslate2.libs/ 隐藏目录(pip wheel 拆分产物),不在 ctranslate2/ 包目录。
|
||
RUN for d in /usr/local/lib/python3.12/site-packages/ctranslate2.libs \
|
||
/usr/local/lib/python3.12/site-packages/ctranslate2; do \
|
||
[ -d "$d" ] && find "$d" -name '*.so*' \
|
||
-exec patchelf --clear-execstack {} \; 2>/dev/null || true; \
|
||
done; \
|
||
python -c "import ctranslate2; print('ctranslate2 stack fix verified', ctranslate2.__version__)"
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 3. dev:从 deps 继承依赖,不 COPY 代码(compose 用 volume 挂载源码)。
|
||
# 开启 uvicorn --reload,改代码零重建、保存即生效。
|
||
# 注意:dev 必须在 final 之前,保证 `docker build` 默认 target 是 final。
|
||
# ---------------------------------------------------------------------------
|
||
FROM deps AS dev
|
||
VOLUME ["/data", "/models"]
|
||
# ctranslate2/faster-whisper 用系统动态链接器找 cuDNN(不走 torch 的库加载),
|
||
# 需把 torch wheel 自带的 nvidia 库目录加入 LD_LIBRARY_PATH,否则 GPU 推理报
|
||
# "Unable to load libcudnn_ops.so.9"。放在 final/dev 而非 deps,避免 ENV 变化
|
||
# 导致 deps 的 apt/pip 层缓存失效。CPU 镜像无此目录,路径被忽略不影响。
|
||
ENV CONFIG_PATH=/app/config.yaml \
|
||
LD_LIBRARY_PATH=/usr/local/lib/python3.12/site-packages/nvidia/cudnn/lib:/usr/local/lib/python3.12/dist-packages/nvidia/cudnn/lib:/usr/local/lib/python3.12/site-packages/nvidia/cublas/lib:/usr/local/lib/python3.12/dist-packages/nvidia/cublas/lib
|
||
|
||
EXPOSE 8000
|
||
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 4. final(prod):从 deps 继承全部依赖,只加 app 代码。
|
||
# 放在最后 = `docker build` 默认 target。setup.sh / start.sh 依赖此默认行为。
|
||
# ---------------------------------------------------------------------------
|
||
FROM deps AS final
|
||
COPY app /app/app
|
||
COPY scripts /app/scripts
|
||
COPY config.example.yaml /app/config.example.yaml
|
||
|
||
# 运行时数据:上传 / 中间产物 / 输出字幕 / 模型缓存
|
||
# 全部走 volume,镜像本身无状态、无敏感数据
|
||
VOLUME ["/data", "/models"]
|
||
ENV CONFIG_PATH=/app/config.yaml \
|
||
LD_LIBRARY_PATH=/usr/local/lib/python3.12/site-packages/nvidia/cudnn/lib:/usr/local/lib/python3.12/dist-packages/nvidia/cudnn/lib:/usr/local/lib/python3.12/site-packages/nvidia/cublas/lib:/usr/local/lib/python3.12/dist-packages/nvidia/cublas/lib
|
||
|
||
EXPOSE 8000
|
||
CMD ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
|