# Stage 1: 构建前端 FROM node:20-alpine AS frontend-builder ARG NPM_REGISTRY=https://registry.npmmirror.com WORKDIR /app/frontend COPY frontend/package*.json ./ RUN --mount=type=cache,target=/root/.npm \ npm install --registry=${NPM_REGISTRY} COPY frontend/ . RUN npm run build # Stage 2: Python 后端 FROM python:3.12-slim ARG PIP_INDEX=https://mirrors.aliyun.com/pypi/simple/ WORKDIR /app # 先只 COPY requirements.txt,利用 Docker 层缓存——只要依赖不变就命中缓存 COPY requirements.txt . # 用 --only-binary=:all: 强制只下载预编译 wheel,避免编译 scikit-learn # 若平台无 wheel 会报错,但 x86_64 上 scikit-learn/numpy/scipy 都有 RUN --mount=type=cache,target=/root/.cache/pip \ pip install --no-cache-dir -r requirements.txt \ -i ${PIP_INDEX} \ --trusted-host mirrors.aliyun.com \ --only-binary=:all: \ || pip install --no-cache-dir -r requirements.txt \ -i ${PIP_INDEX} \ --trusted-host mirrors.aliyun.com # 创建非 root 用户(不需要 gcc 了,去掉 apt-get 节省 ~40s) RUN useradd --create-home --uid 1000 app COPY . . COPY --from=frontend-builder /app/frontend/dist ./static # 确保数据目录对 app 用户可写 RUN mkdir -p /app/data && chown -R app:app /app/data USER app EXPOSE 7331 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7331", "--workers", "1"]