You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Docker中用FastAPI托管Vite.js React项目静态文件

FastAPI 托管 Vite React 静态文件统一部署方案

核心问题根因

你遇到的三类报错本质是三个通用配置坑:

  • 静态文件路径使用了相对启动目录的硬编码路径,切换工作目录(从backend切到项目根目录、切到容器内工作目录)时路径解析失效
  • 静态文件挂载方式不符合SPA单页应用的路由规则,且挂载顺序/前缀配置错误导致404
  • Docker构建上下文配置错误,导致容器内前端静态文件没有被正确拷贝到对应路径

分步修复方案

1. 修复路径解析逻辑(彻底解决目录不存在报错)

不要用字符串形式的相对路径(比如frontend/dist、../frontend/dist),这类路径是相对于执行uvicorn命令时的工作目录解析的,和代码文件位置无关,切换启动位置就会失效。
基于当前Python代码文件的位置拼接绝对路径,和启动目录无关:
在你的backend/main.py中添加路径计算逻辑:

from pathlib import Path
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse

app = FastAPI()

# 计算绝对路径:BASE_DIR是当前main.py所在的backend目录的绝对路径
BASE_DIR = Path(__file__).resolve().parent
# 前端构建产物目录:项目根目录/frontend/dist
STATIC_ASSETS_DIR = BASE_DIR.parent / "frontend" / "dist"

2. 正确配置静态路由(解决访问404问题)

注意两个配置规则:

  • 所有后端API路由要定义在静态路由之前,避免静态路由优先级过高覆盖API
  • React是SPA应用,前端路由需要fallback到index.html,原生StaticFiles挂载不支持自动fallback,需要单独加捕获路由
    完整路由配置示例:
# 先定义所有后端API路由,举个例子
@app.get("/api/health")
def health_check():
    return {"status": "running"}

# 挂载静态资源(js/css/fonts等带hash的资源,直接走StaticFiles即可)
app.mount(
    "/assets",
    StaticFiles(directory=STATIC_ASSETS_DIR / "assets"),
    name="static-assets"
)

# 捕获所有非API路径,处理SPA路由
@app.get("/{full_path:path}")
def serve_frontend(full_path: str):
    # 如果请求路径对应dist目录下的真实文件(比如favicon.ico、根目录的logo等),直接返回文件
    target_file = STATIC_ASSETS_DIR / full_path
    if target_file.is_file():
        return FileResponse(target_file)
    # 其他所有路径(包括前端路由路径、不存在的前端路径)统一返回index.html,交给React Router处理
    return FileResponse(STATIC_ASSETS_DIR / "index.html")

配置完成后本地验证:

  • 在项目根目录执行uvicorn backend.main:app可以正常启动,无目录不存在报错
  • 在backend目录执行uvicorn main:app同样可以正常启动
  • 访问http://127.0.0.1:8000即可正常打开前端页面,刷新前端子路由不会返回404
  • 访问/api/health等后端接口正常返回,不会被前端路由拦截

3. 修复Dockerfile配置(解决容器运行报错)

容器内报路径不存在,除了之前的硬编码相对路径问题,还有两个常见错误:Docker构建上下文选在backend目录导致无法拷贝frontend的文件、静态文件没有被正确拷贝到容器内的对应路径。
在项目根目录创建如下Dockerfile(不要放在backend目录):

# 第一阶段:构建前端产物
FROM node:20-alpine AS frontend-build
WORKDIR /build/frontend
COPY frontend/package*.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build

# 第二阶段:构建最终运行镜像
FROM python:3.11-slim
WORKDIR /app
# 安装后端依赖
COPY backend/requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
# 拷贝后端代码到/app/backend目录
COPY backend/ ./backend/
# 把前端构建的dist目录拷贝到/app/frontend/dist,和本地目录结构完全一致
COPY --from=frontend-build /build/frontend/dist ./frontend/dist/
EXPOSE 8000
# 启动服务,因为我们用了基于代码文件的绝对路径,这里工作目录不管怎么设都不会路径错误
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]

构建镜像时必须在项目根目录执行构建命令,保证构建上下文能同时访问backend和frontend两个目录:

docker build -t fullstack-app .

运行容器后访问对应端口即可正常打开服务,不会出现目录不存在或404错误。


内容的提问来源于stack exchange,提问作者mrpbennett

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 09:54:26