From 1efcf9d5df54b87a16ac3d93a71b469fe1a67416 Mon Sep 17 00:00:00 2001 From: shy3130 <415333856@qq.com> Date: Wed, 24 Jun 2026 11:22:15 +0800 Subject: [PATCH] =?UTF-8?q?fix(docker):=20=E4=BF=AE=E5=A4=8D=E5=9B=BD?= =?UTF-8?q?=E5=86=85=E7=BD=91=E7=BB=9C=E6=9E=84=E5=BB=BA=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E4=B8=8E=E5=89=8D=E7=AB=AF=E9=9D=99=E6=80=81=E6=96=87=E4=BB=B6?= =?UTF-8?q?=20404?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两个独立问题: 1. 构建阶段网络失败 - corepack 不读 npm 的 registry 配置, 且环境变量跨 RUN 不保留, 导致国内网络下 corepack 反复从 registry.npmjs.org 拉取 pnpm 失败。 - 改为直接 `npm install -g pnpm@9` (npm 会读取 .npmrc 镜像源) 彻底绕开。 - 新增 USE_CN_MIRROR/NPM_REGISTRY/PYPI_INDEX build-arg, 默认启用 npmmirror + 清华 PyPI, 可 --build-arg USE_CN_MIRROR=0 关闭。 2. 容器启动后 GET / 返回 404 - config.py 的 _PROJECT_ROOT 按开发布局 (/backend/app/) 推导, Docker 里 backend/app 被拷到 /app/app, 导致其错算到系统根目录 /, static_dir 解析成不存在的 /frontend/dist, 静态挂载被跳过。 - 用 ENV 显式指定 STATIC_DIR / TIERS_YAML / DATA_DIR 指向容器内正确路径, 无需改动 Python 代码, 桌面版 (PyInstaller frozen) 逻辑不受影响。 --- Dockerfile | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3cd5b04..71641f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,21 @@ # 两阶段构建:前端 dist 拷进后端镜像,单容器运行 +# 可选:构建网络无法直连官方源时,传入 --build-arg USE_CN_MIRROR=1 启用国内镜像 +ARG USE_CN_MIRROR=1 +ARG NPM_REGISTRY=https://registry.npmmirror.com +ARG PYPI_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple + # === Stage 1: 前端构建 === FROM node:20-alpine AS frontend-builder +ARG USE_CN_MIRROR=1 +ARG NPM_REGISTRY=https://registry.npmmirror.com WORKDIR /build -RUN corepack enable && corepack prepare pnpm@9 --activate +# 关键:corepack 不读 npm 的 registry 配置,且跨 RUN 不保留环境变量, +# 因此国内网络下最稳的做法是直接用 npm 安装 pnpm(npm 会读取 .npmrc 镜像源), +# 彻底绕开 corepack 再次联网下载 pnpm 的问题。 +RUN if [ "$USE_CN_MIRROR" = "1" ]; then npm config set registry "$NPM_REGISTRY"; fi && \ + npm install -g pnpm@9 +# 让 pnpm 走镜像源安装依赖 +RUN if [ "$USE_CN_MIRROR" = "1" ]; then pnpm config set registry "$NPM_REGISTRY"; fi COPY frontend/package.json frontend/pnpm-lock.yaml* ./ RUN pnpm install --frozen-lockfile || pnpm install COPY frontend/ ./ @@ -10,19 +23,32 @@ RUN pnpm build # === Stage 2: Python 运行时 === FROM python:3.11-slim AS runtime +ARG USE_CN_MIRROR=1 +ARG PYPI_INDEX=https://pypi.tuna.tsinghua.edu.cn/simple WORKDIR /app # 安装 uv(快) -RUN pip install --no-cache-dir uv +RUN if [ "$USE_CN_MIRROR" = "1" ]; then \ + pip install --no-cache-dir uv -i "$PYPI_INDEX"; \ + else \ + pip install --no-cache-dir uv; \ + fi # Backend deps COPY README.md /README.md COPY backend/pyproject.toml backend/uv.lock* ./ -RUN uv sync --frozen --no-dev || uv sync --no-dev +RUN if [ "$USE_CN_MIRROR" = "1" ]; then export UV_DEFAULT_INDEX="$PYPI_INDEX"; fi; \ + uv sync --frozen --no-dev || uv sync --no-dev # Backend code +# 注意:Docker 里 WORKDIR=/app, 而 config.py 的 _PROJECT_ROOT 是按开发布局 +# (/backend/app/) 推导的, 容器内会错算到 /。这里用环境变量显式指定 +# 三个关键路径, 确保 static / tiers / data 都指向容器内正确位置。 COPY backend/app ./app COPY tiers.yaml /app/tiers.yaml +ENV STATIC_DIR=/app/static \ + TIERS_YAML=/app/tiers.yaml \ + DATA_DIR=/app/data # Frontend 静态产物 COPY --from=frontend-builder /build/dist ./static