Vue + FastAPI 怎样在生产环境部署

如果是在开发环境中的运行方法:

在一个终端中 , 启动后端

fastapi run api/main.py

打开另一个终端,启动前端:
npm run dev

项目打包生产环境正式部署方法:

要将 Vue 前端和 FastAPI 后端部署在同一台电脑上,并充分利用多 CPU 且避免跨域问题,最简便的方法是使用 反向代理 和 进程管理器。以下是详细步骤和解释:

  1. 项目准备:
  • Vue 前端:

    • 确保你的 Vue 项目已经构建(npm run build),生成 dist 目录(或其他配置的输出目录)。
    • Vue 项目中与后端 API 交互时,使用相对路径(例如 /api/users)或环境变量配置的基础 URL。不要硬编码后端地址和端口。
  • FastAPI 后端:

    • 确保你的 FastAPI 应用可以正常运行。
    • FastAPI 应用监听一个端口(例如 8000)。
  1. 安装和配置 Nginx (反向代理):

Nginx 是一个高性能的 Web 服务器和反向代理服务器。我们将使用它来:

  • 提供 Vue 前端的静态文件服务。

  • 将前端发出的 API 请求转发到 FastAPI 后端。

  • 处理跨域问题。

  • 安装 Nginx:

    • Windows: 下载 Nginx for Windows ,解压到你喜欢的目录。
    • macOS: 使用 Homebrew 安装: brew install nginx
    • Linux (Ubuntu/Debian): sudo apt update && sudo apt install nginx
    • Linux (CentOS/RHEL): sudo yum install epel-release && sudo yum install nginx
  • 配置 Nginx:

    • 找到 Nginx 的配置文件:

      • Windows: conf/nginx.conf (在 Nginx 解压目录下)
      • macOS: /usr/local/etc/nginx/nginx.conf (或 /opt/homebrew/etc/nginx/nginx.conf,取决于 Homebrew 安装位置)
      • Linux: /etc/nginx/nginx.conf/etc/nginx/conf.d/default.conf
    • 修改配置文件 (nginx.conf): 用以下内容替换或修改 server 块:

    server {
        listen 80;  # 监听 80 端口 (HTTP 默认端口)
        server_name localhost; # 或你的域名 (如果部署到服务器)
    
        # Vue 前端静态文件
        location / {
            root   /path/to/your/vue/dist;  # 替换为你的 Vue 项目 dist 目录的绝对路径
            index  index.html;
            try_files $uri $uri/ /index.html; # 处理 Vue Router 的 history 模式
        }
    
        # FastAPI 后端 API 代理
        location /api {
            proxy_pass http://127.0.0.1:8000;  # 转发到 FastAPI 后端 (假设 FastAPI 监听 8000 端口)
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    
        # 可选: 启用 gzip 压缩 (提高性能)
        gzip on;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml+rss text/javascript;
    }
    
    • 关键配置解释:

      • listen 80;: Nginx 监听 80 端口,这是 HTTP 的默认端口。你可以根据需要更改。
      • root /path/to/your/vue/dist;: 指定 Vue 构建后的 dist 目录的绝对路径。
      • try_files $uri $uri/ /index.html;: 这是处理 Vue Router 使用 history 模式的关键。它确保所有非文件请求都重定向到 index.html,由 Vue Router 处理。
      • location /api: 定义一个以 /api 开头的 URL 路径。
      • proxy_pass http://127.0.0.1:8000;: 将 /api 开头的请求转发到 FastAPI 后端,假设 FastAPI 运行在本地的 8000 端口。
      • proxy_set_header ...: 设置一些请求头,以便后端可以获取客户端的真实 IP 地址等信息。
      • gzip on;: 启用 gzip 压缩,可以减少传输的数据量,提高性能。
    • 测试 Nginx 配置:

      • Windows: 在 Nginx 目录下打开命令行,运行 nginx -t
      • macOS/Linux: sudo nginx -t
      • 如果没有错误,继续下一步。
    • 启动/重启 Nginx:

      • Windows: 双击 nginx.exe 启动,或在命令行运行 nginx。 要重启,运行 nginx -s reload
      • macOS: brew services start nginx (启动) 或 brew services restart nginx (重启)
      • Linux: sudo systemctl start nginx (启动) 或 sudo systemctl restart nginx (重启)
  1. 使用 Uvicorn (或 Gunicorn) 和进程管理器启动 FastAPI:

Uvicorn 是一个 ASGI 服务器,用于运行 FastAPI 应用。Gunicorn 是一个 WSGI/ASGI 服务器,可以管理多个 Uvicorn 进程,充分利用多 CPU。

  • 安装 Uvicorn 和 Gunicorn (如果尚未安装):

    pip install uvicorn gunicorn
    
  • 启动 FastAPI (使用 Uvicorn):

    uvicorn your_app_module:app --host 0.0.0.0 --port 8000 --reload  # 开发环境
    
    • your_app_module: 你的 FastAPI 应用的主模块文件 (例如 main.py,则写 main)。
    • app: 你的 FastAPI 应用实例的名称 (通常是 app = FastAPI())。
    • --host 0.0.0.0: 监听所有网络接口 (重要,这样 Nginx 才能通过 127.0.0.1 访问)。
    • --port 8000: FastAPI 监听的端口 (与 Nginx 配置中的 proxy_pass 对应)。
    • --reload: (可选) 启用代码热重载,方便开发。
  • 启动 FastAPI (使用 Gunicorn, 充分利用多 CPU):

    gunicorn your_app_module:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
    
    • -w 4: 启动 4 个 worker 进程 (根据你的 CPU 核心数调整)。
    • -k uvicorn.workers.UvicornWorker: 指定使用 Uvicorn worker。
    • -b 0.0.0.0:8000: 绑定到所有接口的 8000 端口。

    更推荐的方式:使用进程管理器(如 pm2 (Node.js) 或 supervisor (Python))来管理 Gunicorn 进程,可以实现自动重启、日志管理等功能。

    • 使用 pm2 (Node.js 环境):

      1. 全局安装 pm2: npm install -g pm2
      2. 启动 FastAPI:
        pm2 start "gunicorn your_app_module:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000" --name fastapi-app
        
      3. 保存当前进程列表: pm2 save
      4. 设置开机自启: pm2 startup (按照提示操作)
    • 使用 Supervisor (Python 环境):

      1. 安装 Supervisor: pip install supervisor

      2. 创建 Supervisor 配置文件 (例如 supervisord.conf):

        [program:fastapi-app]
        command=gunicorn your_app_module:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
        directory=/path/to/your/fastapi/project  ; FastAPI 项目目录
        autostart=true
        autorestart=true
        stderr_logfile=/var/log/fastapi-app.err.log
        stdout_logfile=/var/log/fastapi-app.out.log
        
      3. 启动 Supervisor: supervisord -c supervisord.conf

      4. 使用 supervisorctl 管理进程 (例如 supervisorctl status, supervisorctl restart fastapi-app)。 配置开机自启通常需要将 supervisord 添加到系统服务。

  1. 访问你的应用:

现在,你应该可以通过浏览器访问 http://localhost (或 http://localhost:80,如果 Nginx 监听的是 80 端口) 来访问你的 Vue 前端。前端发出的以 /api 开头的请求会被 Nginx 转发到 FastAPI 后端,不会有跨域问题。

总结:

这种部署方式的优点:

  • 简便: 只需要配置 Nginx 和一个进程管理器。
  • 高性能: Nginx 处理静态文件非常高效,Gunicorn/Uvicorn 可以充分利用多 CPU。
  • 无跨域问题: 前端和后端通过 Nginx 在同一个域名下提供服务,避免了跨域。
  • 易于扩展: 如果需要部署到服务器,只需要将 Nginx 配置中的 server_name 改为你的域名,并将代码部署到服务器即可。
  • 生产环境就绪: 使用了生产环境推荐的服务器和进程管理器

重要提示:

  • 确保防火墙允许 80 端口 (或你配置的 Nginx 端口) 的流量。
  • 在生产环境中,建议使用 HTTPS (配置 SSL 证书)。
  • 根据你的实际情况调整 Nginx 和 Gunicorn/Uvicorn 的配置。
  • 强烈建议使用进程管理器 (pm2 或 Supervisor) 来管理 FastAPI 进程。
  • 如果你的前端项目使用了其他的 URL 路径(不仅仅是/api)与后端交互,你需要在 Nginx 配置中添加相应的 location 块进行代理。
  • Windows下,如果遇到路径问题,可以尝试使用双反斜杠 \\ 或正斜杠 / 来表示路径。

这个方案是经过实践验证的,非常适合将 Vue 和 FastAPI 部署在同一台机器上。

如果从其他电脑访问部署在 IP 地址为 192.168.61.3 的服务,Vue 和 FastAPI 代码中不需要写明这个 IP 地址。关键在于 Nginx 的配置和前端 API 请求的写法。

  1. Nginx 配置 (无需修改):

你之前在 Nginx 的 nginx.conf 中的配置:

server {
    listen 80;
    server_name localhost;  # 这里保持 localhost 或改为 192.168.61.3 都可以

    location / {
        root   /path/to/your/vue/dist;
        index  index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api {
        proxy_pass http://127.0.0.1:8000;
        # ... 其他 proxy_set_header ...
    }
}
  • server_name: 这里可以保持 localhost,也可以改为 192.168.61.3localhost 只在服务器本机访问时有效,而 192.168.61.3 可以从局域网内的其他电脑访问。 更推荐的做法是:

    • 开发环境: 保持 localhost
    • 局域网测试/部署: 改为 192.168.61.3 (或服务器的实际 IP)。
    • 生产环境 (有域名): 改为你的域名 (例如 example.com)。
  • proxy_pass http://127.0.0.1:8000;: 这个配置非常重要。它告诉 Nginx 将 /api 开头的请求转发到 服务器本机 的 8000 端口。 因为 FastAPI 是在服务器上运行的,所以 Nginx 总是通过 127.0.0.1 (本地回环地址) 来访问 FastAPI,无论外部客户端从哪个 IP 地址访问。

  1. Vue 代码 (使用相对路径或环境变量):

在 Vue 代码中,与后端 API 交互时,不要硬编码任何 IP 地址或端口。使用以下两种方式之一:

  • 相对路径 (推荐):

    // 假设你的 API 基础路径是 /api
    fetch('/api/users')
      .then(response => response.json())
      .then(data => console.log(data));
    
    // 或者使用 axios
    axios.get('/api/users')
      .then(response => console.log(response.data));
    

    这种方式最简单,也最灵活。因为 Nginx 已经配置了 /api 路径的代理,所以 Vue 发出的 /api/users 请求会被 Nginx 自动转发到 FastAPI。

  • 环境变量 (更灵活):

    1. 在 Vue 项目的根目录下创建 .env 文件 (或 .env.development, .env.production 等,根据你的环境)。

    2. .env 文件中定义一个变量:

      VUE_APP_API_BASE_URL=/api
      

      或者,如果你想在开发环境和生产环境使用不同的基础URL,可以这样:
      .env.development:

      VUE_APP_API_BASE_URL=/api
      

      .env.production:

      VUE_APP_API_BASE_URL=/api  
      # 或者,如果生产环境的 API 基础路径不同,可以修改
      
    3. 在 Vue 代码中使用这个变量:

      const apiBaseUrl = process.env.VUE_APP_API_BASE_URL;
      
      fetch(`${apiBaseUrl}/users`)
        .then(response => response.json())
        .then(data => console.log(data));
      
      // 或者使用 axios
      axios.get(`${apiBaseUrl}/users`)
        .then(response => console.log(response.data));
      

    使用环境变量的好处是,你可以根据不同的环境 (开发、测试、生产) 轻松切换 API 的基础 URL,而无需修改代码。

  1. FastAPI 代码 (无需修改):

FastAPI 代码中不需要做任何修改。它只需要监听本地的 8000 端口 (或其他你配置的端口),并通过 Uvicorn/Gunicorn 启动即可。

  1. 客户端访问:

其他电脑上的用户,只需要在浏览器中输入服务器地址就可以访问你的 Vue 应用。 Vue 应用发出的 API 请求会被 Nginx 转发到 FastAPI,整个过程对客户端是透明的。

总结:

  • Nginx 作为反向代理,负责将客户端请求转发到正确的后端服务。
  • Vue 代码使用相对路径或环境变量来构建 API 请求,不依赖于具体的 IP 地址。
  • FastAPI 只需要监听本地端口。
  • 客户端通过服务器的 IP 地址访问 Nginx,Nginx 再将请求转发到 FastAPI。

这种架构使得你的应用部署非常灵活,无论是在本地开发、局域网测试,还是部署到远程服务器,都不需要修改 Vue 或 FastAPI 的代码。只需要修改 Nginx 的 server_name 和 Vue 的环境变量 (如果需要) 即可。

在这种部署方式下(使用 Nginx 反向代理),FastAPI 后端程序通常不需要 CORSMiddleware 中间件。

原因:

  • 同源策略: 跨域资源共享 (CORS) 是浏览器的一种安全机制,用于限制从一个源(协议、域名、端口)加载的网页去请求另一个源的资源。

  • Nginx 反向代理的作用: 当你使用 Nginx 作为反向代理时,Vue 前端和 FastAPI 后端都通过 Nginx 的同一个端口(例如 80)提供服务。从浏览器的角度来看,前端和后端是同源的,因为它们具有相同的协议(http 或 https)、相同的域名(或 IP 地址)和相同的端口。

  • 请求流程:

    1. 客户端(浏览器)向 Nginx 发送请求(例如 http://XXXXXXXXXXX/api/users)。
    2. Nginx 根据 location /api 的配置,将请求转发到 FastAPI 后端(http://127.0.0.1:8000/users)。
    3. FastAPI 处理请求并返回响应给 Nginx。
    4. Nginx 将响应返回给客户端。

    在这个过程中,浏览器只与 Nginx 交互,它认为所有请求都是发往同一个源的,因此不会触发 CORS 限制。

何时仍然需要 CORSMiddleware

尽管在大多数情况下不需要 CORSMiddleware,但在以下情况下,你可能仍然需要它:

  1. 直接访问 FastAPI: 如果你允许客户端(例如其他应用程序或脚本)直接访问 FastAPI 的端口(例如 http://XXXXXXXXXXXXXX:8000),而不是通过 Nginx,那么就需要 CORSMiddleware 来处理跨域请求。

  2. 子域名或不同端口: 如果你的 Vue 前端和 FastAPI 后端部署在不同的子域名(例如 frontend.example.comapi.example.com)或不同的端口上,即使它们都在同一台服务器上,浏览器仍然会认为它们是不同的源,需要 CORSMiddleware

  3. 复杂的 CORS 需求: 如果你有更复杂的 CORS 需求,例如需要精确控制允许的来源、方法、头部等,那么即使使用了 Nginx 反向代理,也可能需要使用 CORSMiddleware 来进行更细粒度的配置。

最佳实践:

  • 优先使用 Nginx 反向代理解决跨域问题: 这是最简单、最有效的方法。
  • 如果确实需要 CORSMiddleware
    • 在 FastAPI 中添加 CORSMiddleware

      from fastapi import FastAPI
      from fastapi.middleware.cors import CORSMiddleware
      
      app = FastAPI()
      
      origins = [
          "http://localhost",  # 允许本地访问
          "http://XXXXXXXXXX", # 允许局域网访问
          "http://XXXXXXXXXX", # 允许你的域名访问
          # ... 其他允许的来源 ...
      ]
      
      app.add_middleware(
          CORSMiddleware,
          allow_origins=origins,
          allow_credentials=True,
          allow_methods=["*"],  # 允许所有方法 (GET, POST, PUT, DELETE, etc.)
          allow_headers=["*"],  # 允许所有头部
      )
      
      # ... 你的 API 路由 ...
      
    • allow_origins: 指定允许访问的来源列表。你可以使用 "*" 来允许所有来源(不推荐在生产环境中使用)。

    • allow_credentials: 如果你的 API 需要使用 cookies 或 HTTP 认证,设置为 True

    • allow_methods: 指定允许的 HTTP 方法。

    • allow_headers: 指定允许的 HTTP 头部。

总结:

在 Nginx 反向代理的部署方式下,FastAPI 通常不需要 CORSMiddleware,因为 Nginx 已经解决了跨域问题。只有在特殊情况下(例如直接访问 FastAPI、不同的子域名或端口、复杂的 CORS 需求)才需要使用 CORSMiddleware。 优先通过 Nginx 解决跨域问题,保持后端代码的简洁。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,492评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,048评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,927评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,293评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,309评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,024评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,638评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,546评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,073评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,188评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,321评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,998评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,678评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,186评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,303评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,663评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,330评论 2 358

推荐阅读更多精彩内容