ubuntu上部署koa+react项目

107 阅读10分钟

在 Ubuntu 服务器上部署 Koa (后端) 和 React (前端) 项目,IT 部门询问端口开放的问题,核心在于如何让外部用户访问你的应用。端口是网络通信的入口,必须开放端口才能让外部访问

核心结论:

  1. 不开端口无法部署(让外部访问):  如果不开放任何端口,外部网络根本无法连接到你的服务器上的应用,你的项目只能在服务器本地访问,失去了部署的意义。必须开放端口!

  2. 开端口是必须的,但策略不同:  开多少个端口、开哪些端口,取决于你选择的部署架构。常见的有两种主要方式(后面详细解释):

    • 方式一:只开一个端口 (推荐且更安全)
    • 方式二:开两个端口
  3. 端口不能完全“随便”:

    • 标准端口 (80/443) 最佳:  HTTP 默认端口是 80, HTTPS 默认端口是 443。用户访问 http://你的域名 或 http://公网IP 时,浏览器默认就是访问 80 端口;访问 https://... 默认访问 443 端口。使用标准端口用户体验最好(用户无需在URL中输入端口号)。
    • 非标准端口可用但有缺点:  你可以选择其他端口(如 300080808989 等)。缺点:  用户访问时必须在域名/IP 后面加上 :端口号 (如 http://yourdomain.com:8080),不够友好,容易被忘记,且某些企业防火墙可能阻止非常用端口。IT 部门可能也会建议优先使用标准端口。
    • 特权端口限制:  端口号小于 1024 (如 80443) 是“特权端口”,普通用户进程通常无法直接监听,需要使用 sudo 或以 root 身份运行(不推荐),或者更常见的做法是让一个非特权进程(如 Nginx)监听 80/443,然后将请求转发(反向代理)到你的应用进程(运行在 >1024 的端口,如 30008989)上。这是最佳实践

详细部署方案分析:

方案一:只开放一个端口 (强烈推荐 - 80 或 443)

  • 核心思想:  使用 Nginx (或 Apache, Caddy 等) Web 服务器作为反向代理和静态文件服务器,只对外暴露 80 (HTTP) 或 443 (HTTPS) 这一个端口。

  • 架构:

    text

    用户浏览器 <-----> [Nginx 监听 80/443] <-----> (反向代理) <-----> [Koa 后端应用 监听 127.0.0.1:8989 (内部端口)]
                                    ^
                                    |
                                    (服务静态文件) <-----> [React 前端 build 后的静态文件]
    
  • 流程:

    1. 构建 React 前端:  在你的开发机上运行 npm run build (或 yarn build),生成一个包含 HTML, JS, CSS, 图片等静态文件的 build (或 dist) 目录。

    2. 部署 React 静态文件:  将整个 build 目录上传到服务器,放在 Nginx 能够访问的位置 (如 /var/www/your-frontend)。

    3. 部署 Koa 后端:  将你的 Koa 项目代码部署到服务器。确保它能正常运行并监听服务器内部的一个端口(比如 8989)。强烈建议使用进程管理器 (如 pm2) 来运行 Node.js 应用pm2 start your-koa-app.js

    4. 安装并配置 Nginx:

      • 安装:sudo apt update && sudo apt install nginx

      • 创建配置文件 (如 /etc/nginx/sites-available/your-project):

        nginx

        server {
            listen 80; # 监听 HTTP 端口 80。如果需要 HTTPS,应改为 listen 443 ssl; 并配置 SSL 证书
            server_name yourdomain.com; # 你的域名或服务器公网IP(如果没域名)
        
            # 配置 React 前端 (静态文件)
            location / {
                root /var/www/your-frontend/build; # 指向你上传的 React build 目录
                try_files $uri $uri/ /index.html; # 支持 React Router 的 BrowserHistory
                index index.html;
            }
        
            # 配置 Koa 后端 API 的反向代理 (假设你的 API 以 /api 开头)
            location /api {
                proxy_pass http://127.0.0.1:8989; # 转发到 Koa 应用监听的内部地址和端口
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                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;
                proxy_cache_bypass $http_upgrade;
            }
        
            # 可选:其他静态资源路径(如果前端build里没有,或者有单独的上传目录等)
            # location /uploads {
            #    alias /path/to/your/uploads;
            # }
        }
        
      • 启用配置:sudo ln -s /etc/nginx/sites-available/your-project /etc/nginx/sites-enabled/

      • 测试配置:sudo nginx -t (必须确保配置语法正确)

      • 重启 Nginx:sudo systemctl restart nginx

    5. 告诉 IT 部门:  只需开放 80 端口 (HTTP) 和/或 443 端口 (HTTPS) 。强烈建议最终使用 HTTPS (443),可以使用 Let's Encrypt 免费证书 (certbot 工具自动化)。

  • 用户访问:

    • 用户访问 http://yourdomain.com (或 http://公网IP) -> Nginx 返回 React 前端页面。
    • 前端页面中的 JavaScript 代码请求 /api/some-endpoint -> 浏览器请求 http://yourdomain.com/api/some-endpoint -> Nginx 匹配到 location /api -> 将请求转发给服务器内部 127.0.0.1:8989/api/some-endpoint -> Koa 处理请求并返回结果 -> Nginx 将结果返回给浏览器前端。
  • 优点:

    • 安全:  只暴露一个标准端口 (80/443),攻击面小。后端应用 (Koa) 只监听内部地址 (127.0.0.1),外部无法直接访问。
    • 专业 & 标准:  符合 Web 服务标准部署方式。
    • 高性能 & 稳定:  Nginx 擅长处理静态文件和并发连接,减轻 Node.js 负担。进程管理器 (pm2) 保证 Node.js 应用崩溃后自动重启。
    • 用户体验好:  用户无需输入端口号。
    • 灵活:  方便后续添加 SSL、负载均衡、缓存等。
  • 缺点:  需要学习配置 Nginx。

方案二:开放两个端口 (不推荐,次选方案)

  • 核心思想:  前端和后端各自直接监听不同的端口,并直接对外暴露。

  • 架构:

    text

    用户浏览器 <-----> [React 前端 监听 端口A (如 3000)]
    用户浏览器 <-----> [Koa 后端 监听 端口B (如 8989)]
    
  • 流程:

    1. 构建 React 前端:  同样 npm run build

    2. 部署 React 前端:

      • 在服务器上,使用一个静态 HTTP 服务器 (如 servehttp-server) 来服务 build 目录。
      • 安装静态服务器 (例如 serve):sudo npm install -g serve
      • 运行:serve -s -l 3000 /var/www/your-frontend/build (-s 处理 SPA 路由, -l 3000 指定监听端口 3000)。同样建议用 pm2 管理:pm2 serve /var/www/your-frontend/build 3000 --spa
    3. 部署 Koa 后端:

      • 部署代码。
      • 运行:pm2 start your-koa-app.js (确保你的 Koa 应用配置为监听 0.0.0.0 和指定的端口,如 8989)。重要:  为了外部能访问,必须监听 0.0.0.0 (所有网络接口),而不仅仅是 127.0.0.1
    4. 告诉 IT 部门:  需要开放两个端口:  前端端口 (如 3000) 和 后端端口 (如 8989)。

  • 用户访问:

    • 用户访问 http://公网IP:3000 -> 访问到 React 前端。
    • 前端代码中配置的 API 地址必须是 http://公网IP:8989/api/...
    • 浏览器直接请求 http://公网IP:8989/api/some-endpoint -> 访问到 Koa 后端。
  • 问题与缺点:

    • 跨域问题 (CORS):  前端运行在 端口A,后端运行在 端口B,浏览器会因为同源策略阻止前端 JS 直接访问不同端口的后端 API。你必须在 Koa 后端应用中显式配置 CORS 头部 (使用 @koa/cors 或类似中间件) 允许来自前端域/端口的请求。
    • 安全性差:  直接暴露了 Node.js 应用 (Koa) 到公网,容易受到针对 Node.js/Express/Koa 的直接攻击。Nginx 作为反向代理可以提供额外的安全层(如限制请求速率、过滤恶意请求)。
    • 用户体验差:  用户访问 URL 需要带前端端口号 (http://ip:3000)。前端代码里需要写死后端 IP 和端口号 (http://ip:8989/api),如果端口或 IP 变动很麻烦。
    • 端口非标准:  用户看到非标准端口可能觉得不专业或不信任。企业防火墙可能阻止非常用端口。
    • 需要管理更多进程和端口:  增加了运维复杂度。
  • 何时考虑此方案?  仅在快速临时测试、内部网络环境、或受限于无法安装/配置 Nginx 等情况下考虑。生产环境强烈不推荐。

回答你的具体问题:

  1. 不开端口能部署吗?  不能。  必须至少开放一个端口才能让外部访问。

  2. 开一个端口怎么部署?  采用方案一 (Nginx 反向代理)。  只开放 80 或 443。Nginx 负责:

    • 直接提供 React 前端的静态文件。
    • 将匹配后端 API 路径 (如 /api) 的请求转发给在 127.0.0.1:8989 运行的 Koa 应用。
  3. 给端口是否随便?

    • 对外暴露的端口:  首选 80 (HTTP) 或 443 (HTTPS)。如果 IT 部门强制要求用其他端口,那就只能用他们给的端口(用户体验会变差)。
    • 内部应用监听端口 (Koa 的 8989, React 静态服务器的 3000):  这个可以“随便”选一个大于 1024 且未被服务器上其他程序占用的端口(如 3000800080808989 等)。在方案一中,这些端口只在服务器内部使用,不直接暴露给公网,所以选择比较自由。在方案二中,这些端口会直接暴露给公网,选择非标准端口会带来用户体验和安全策略上的问题。

总结与强烈建议:

  1. 必须要求 IT 部门开放端口。  最优选是开放 80 (HTTP) 和 443 (HTTPS) 。如果只能开一个,优先 443 (HTTPS) 或 80 (HTTP)。

  2. 采用方案一 (Nginx 反向代理) 部署。  这是生产环境的标准、安全、高效的做法。

    • 前端:Nginx 直接服务构建好的 React 静态文件 (build 目录)。
    • 后端:Koa 应用使用 pm2 运行,监听 127.0.0.1:8989 (或其他你选定的内部端口)。
    • Nginx 配置反向代理,将 /api 等请求转发给后端的内部端口。
  3. 不要采用方案二 (直接暴露两个端口)。  除非有非常特殊的限制且了解并接受其缺点(主要是 CORS 和安全性)。

  4. 使用 pm2 管理 Node.js 进程。  保证应用崩溃自动重启,方便日志管理。

  5. 尽快配置 HTTPS (443端口)。  使用 Let's Encrypt 和 certbot 可以免费自动化获取和更新证书。告诉 IT 部门你需要开放 443 端口用于 HTTPS。

部署步骤概要 (方案一):

  1. 获取公网 IP 和域名 (如有)。

  2. 要求 IT 开放服务器上的 80 和 443 端口 (或至少其中一个)。

  3. 在服务器上:

    • 安装 Node.js, npm/yarn。
    • 安装 Nginx (sudo apt install nginx)。
    • 安装 pm2 (sudo npm install -g pm2)。
  4. 部署前端:

    • 本地构建 React:npm run build
    • 上传 build 目录到服务器 (如 /var/www/your-frontend/build)。
  5. 部署后端:

    • 上传 Koa 项目代码到服务器。
    • npm install 安装依赖。
    • 配置 Koa 应用监听 127.0.0.1:8989 (修改你的 app.listen(8989, '127.0.0.1'))。
    • 用 pm2 启动:pm2 start your-koa-app-entry-file.js --name "koa-api"
  6. 配置 Nginx:

    • 创建配置文件 /etc/nginx/sites-available/your-project (内容参考上面的模板)。
    • 启用配置 (sudo ln -s ... /etc/nginx/sites-enabled/)。
    • 测试并重启 Nginx (sudo nginx -t && sudo systemctl restart nginx)。
  7. (强烈推荐) 配置 HTTPS:

    • 安装 certbot:sudo apt install certbot python3-certbot-nginx
    • 获取并安装证书:sudo certbot --nginx -d yourdomain.com (按提示操作)。
    • 自动续期测试:sudo certbot renew --dry-run
  8. 测试访问你的域名 (或公网IP)。

按照这个流程,你的前后端应用就能通过标准端口安全、稳定地对外提供服务了。