从本地跑通到公网访问:前后端项目部署实战

从本地跑通到公网访问:前后端项目部署实战

摘要:代码在本地跑得好好的,怎么让用户通过域名访问?本文从部署的底层认知出发,拆解服务器选购、安全组与防火墙配置、Nginx 反向代理、宝塔面板可视化管理,以一个全栈项目的完整部署流程为例,帮你打通从"本地跑通"到"线上可访问"的最后一公里。

📑 目录

  • 部署是什么?------ 把菜从厨房端到餐厅
  • 部署的本质:打包 → 上传 → 安装 → 启动
  • 第一步:购买服务器与安全组配置
  • 第二步:宝塔面板------运维的"图形化控制台"
  • 第三步:域名与 DNS------让 IP 变成可读的网址
  • 第四步:Nginx------流量入口的"总调度官"
  • 第五步:部署前端项目
  • 第六步:部署后端项目
  • Nginx 动静分离与反向代理完整配置
  • 互动讨论

部署是什么?------ 把菜从厨房端到餐厅

你写了一个全栈应用:前端是 React 做的精美界面,后端是 Express + MySQL 提供的 API。在本地,npm run dev 一敲,一切正常。

现在问题来了:怎么让全世界的人都能访问这个应用?

这就是部署(Deployment) 要解决的问题。部署的本质是:把运行所需的最小文件集放到服务器上,并在服务器上启动它们。

类比:你做好了一桌菜(开发完成),接下来要把菜从"厨房"(本地开发环境)端到"餐厅"(服务器),让客人(用户)吃。部署就是"端菜"的过程------怎么打包、怎么运输、怎么在服务器上把菜热好端上桌。

部署的本质:打包 → 上传 → 安装 → 启动

部署不是"把整个开发环境搬到服务器上"。标准流程只有四步:

text

复制代码
本地打包 → 上传服务器 → 服务器上安装依赖/构建 → 启动服务

类比:搬家不是把整个房子搬过去,而是把家具打包、运到新家、在新家重新组装摆放。

步骤 前端(React) 后端(Node.js)
打包 npm run builddist/ npm run builddist/
上传 通过 FTP/宝塔文件管理器上传 dist/ 上传源码(或 dist/
安装 不需要(纯静态文件) npm install --production
启动 Nginx 直接返回静态文件 node dist/main.js

第一步:购买服务器与安全组配置

购买服务器

你需要一台有公网 IP 的服务器。对于个人项目和小型应用,轻量云服务器(如腾讯云轻量应用服务器、阿里云 ECS)足够。

购买时需要选择:

  • 操作系统:推荐 Ubuntu 或 CentOS(Linux 生态)
  • 地域:选择离目标用户近的地域
  • 配置:根据项目规模选择 CPU 和内存

安全组------云厂商的"小区大门保安"

服务器买好后,第一件事不是登录,而是配置安全组(Security Group)

误区 :以为在服务器上放行了端口就能被公网访问。

真相安全组和服务器防火墙必须同时放行,流量才能到达应用。

流量走向

text

复制代码
互联网 → 安全组(云平台) → 服务器网卡 → 服务器防火墙(OS) → 应用进程

安全组 (云平台控制台):在流量进入服务器的物理网卡之前拦截。默认全部拒绝,需手动放行端口。由云服务商提供。

端口 用途 建议
22 SSH(远程登录) 建议放行,但改为非默认端口(如 2222)增强安全
80 HTTP 必须放行
443 HTTPS 必须放行(如果配置 SSL)
3000 Node.js 后端 开发时可放行,生产环境建议关闭,走 Nginx 转发
3306 MySQL 绝对不放行(只允许 localhost 访问)

黄金法则 :要让一个端口在公网被访问,必须在安全组服务器防火墙都放行。安全组优先级更高(先经过它)。

第二步:宝塔面板------运维的"图形化控制台"

什么是宝塔面板?

宝塔面板(BT Panel)是一个服务器运维管理面板,通过 Web 界面把 Linux 命令封装成"点按钮"操作,极大降低了运维门槛。

核心价值

  • 文件管理器 :替代 scpmvrm 等命令,在浏览器里拖拽上传、移动、删除文件
  • 软件商店:一键安装 Nginx、MySQL、Redis、PHP 等
  • 网站管理:创建站点、配置反向代理、SSL 证书一键申请
  • 终端:内置 SSH,不用另开客户端

安装宝塔面板

在服务器终端执行以下命令(根据操作系统选择):

bash

bash 复制代码
# Ubuntu/Debian
wget -O install.sh https://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh

# CentOS
yum install -y wget && wget -O install.sh https://download.bt.cn/install/install_6.0.sh && sh install.sh

安装完成后,会显示:

  • 面板访问地址:http://服务器IP:8888
  • 用户名和密码

注意 :需要在安全组中放行 8888 端口才能访问面板。

服务器防火墙

宝塔面板安装后,会在服务器操作系统层面配置防火墙。需要在宝塔的安全菜单中放行所需端口(80、443、22 等)。

类比:安全组 = 小区大门口的保安亭(云厂商提供),服务器防火墙 = 你家房门上的锁(你自己装)。两个都要开,人才能进来。

第三步:域名与 DNS------让 IP 变成可读的网址

http://123.456.789.0 这样的 IP 地址难以记忆和传播。域名就是 IP 的"人类可读版本"。

DNS 解析流程

用户在浏览器输入 example.com 后:

  1. 浏览器缓存:检查本地是否缓存了该域名的 IP
  2. 操作系统缓存:检查系统 hosts 文件和 DNS 缓存
  3. 路由器/局域网 DNS:检查局域网 DNS 服务器缓存
  4. 网络运营商 DNS:递归查询
  5. 根 DNS 服务器 :逐级返回 .comexample.com 的 IP

DNS 的本质是一种分布式数据库,根据域名逐级查找 IP 地址。

在宝塔中添加站点

在宝塔面板的网站 菜单中,点击添加站点

  • 输入域名(如 example.com
  • 选择根目录(如 /www/wwwroot/example
  • 选择是否创建 FTP 和数据库

第四步:Nginx------流量入口的"总调度官"

Nginx 是整个部署架构中的核心入口。它做三件事:

  1. 接受请求
  2. 返回静态文件(直接读磁盘)
  3. 转发动态请求(反向代理给后端)

生产端口策略:只开 Nginx 的端口

生产环境标准做法:只开放 Nginx 的 80/443 端口,后端服务(如 3000)、数据库(3306)全部不对外开放。

  • 外部用户只能访问 Nginx
  • Nginx 在服务器内部转发请求给后端
  • 后端和数据库的攻击面大幅缩小

为什么 Nginx 处理静态文件这么快?

Nginx 处理静态文件时使用 sendfile 系统调用(零拷贝),数据从磁盘直接到网卡,不经过用户态内存拷贝。而 Node.js 处理静态文件时,数据需要从磁盘读到内存,再从内存发给 socket,多了一次拷贝。

所以 Nginx 处理静态文件比 Node.js 快得多,这也是为什么生产环境要把 Nginx 放在 Node.js 前面。

第五步:部署前端项目

在开始部署之前,先看看项目在本地运行时的样子。

此处插入图片:项目在本地运行的截图,显示"FUTURE CAPSULE"标题、输入框、作者、解锁时间设置和"SEAL CAPSULE"按钮,地址栏显示 localhost:5173

这是"未来胶囊"时间胶囊全栈应用的前端界面。用户写下给未来的自己的留言并设定解锁时间,到期前内容不可见。界面设计采用了瀑布流布局,支持无限滚动加载。

本地构建

在本地执行构建命令,生成静态文件:

bash

arduino 复制代码
npm run build
# 产出 dist/ 或 build/ 目录

构建产物包含 .html.css.js 以及图片等静态资源。

此处插入图片:项目加载状态截图,显示"FUTURE_CAPSULE"标题和加载中的提示

上传到服务器

通过宝塔面板的文件管理器,将整个 dist/ 目录上传到服务器的网站根目录(如 /www/wwwroot/example.com/)。

配置 Nginx 站点

在宝塔面板的网站菜单中,创建或编辑站点配置:

nginx

ini 复制代码
server {
    listen 80;
    server_name example.com;

    root /www/wwwroot/example.com;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

try_files 的作用是支持前端路由(React Router 的 BrowserRouter):当访问 /about 这样的路径时,Nginx 会先检查是否存在该文件,如果不存在则返回 index.html,由 React 路由接管。

第六步:部署后端项目

方式一:服务器上构建(推荐)

将源码上传到服务器,在服务器上安装依赖并构建:

bash

bash 复制代码
# 1. 上传源码到服务器(如 /www/wwwroot/api/)
# 2. 安装依赖
npm install --production

# 3. 构建(如果有 TypeScript)
npm run build

# 4. 启动服务
node dist/main.js

方式二:本地构建后上传

在本地构建好后,只上传 dist/ 目录和 package.json,服务器上只需安装生产依赖:

bash

bash 复制代码
# 服务器上
npm install --production
node dist/main.js

使用 PM2 管理进程(推荐)

Node.js 应用需要持久运行 ,不能用 Ctrl+C 的终端方式。PM2 是 Node.js 进程管理器:

bash

bash 复制代码
# 安装 PM2
npm install -g pm2

# 启动应用
pm2 start dist/main.js --name my-api

# 查看状态
pm2 status

# 开机自启
pm2 startup
pm2 save

在宝塔中配置反向代理

在宝塔面板的站点设置中,添加反向代理:

text

arduino 复制代码
目标URL:http://localhost:3000
发送域名:localhost

等价于 Nginx 配置:

nginx

bash 复制代码
location /api/ {
    proxy_pass http://localhost:3000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
}

这样,用户访问 http://example.com/api/users 时,请求被转发到 http://localhost:3000/api/users,由 Node.js 处理。

Nginx 动静分离与反向代理完整配置

将静态资源和动态 API 合并到一个配置文件中:

nginx

bash 复制代码
server {
    listen 80;
    server_name example.com;

    root /www/wwwroot/example.com;
    index index.html;

    # 静态资源:Nginx 直接返回
    location /static/ {
        alias /www/wwwroot/example.com/static/;
        expires 7d;
    }

    # 前端路由:所有非 /api 的请求返回 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 后端 API:转发给 Node.js
    location /api/ {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

互动讨论

💬 部署的本质是什么?

部署的本质是"把运行所需的最小文件集放到服务器上,并在服务器上启动它们",而不是"把整个开发环境搬过去"。

💬 安全组和服务器防火墙有什么区别?

安全组在云平台的物理网卡前拦截,服务器防火墙在操作系统内核中拦截。两者必须同时放行端口,缺一不可。

💬 为什么生产环境只开 Nginx 的端口?

后端服务(如 3000)和数据库(如 3306)不对外开放,所有流量经过 Nginx 转发,减少攻击面。同时 Nginx 处理静态文件比 Node.js 快得多。

💬 前端路由(如 React Router)在 Nginx 上怎么配置?

使用 try_files $uri $uri/ /index.html:当访问 /about 等路径时,Nginx 先检查是否存在该文件,若不存在则返回 index.html,由前端路由接管。

💬 Node.js 应用怎么保证持久运行?

使用 PM2 进程管理器:pm2 start dist/main.js --name my-api。PM2 会在应用崩溃时自动重启,并支持开机自启。

💬 前后端分离项目的跨域问题在部署时怎么解决?

开发阶段用 Vite 代理或 CORS 插件;生产阶段用 Nginx 反向代理将 /api 请求转发给后端,前端请求同源的 /api 路径,不触发跨域。

相关推荐
Jae den1 小时前
服务器 CPU 核心越多越好吗?
运维·服务器
帷幕落秋1 小时前
一文吃透 Nginx 虚拟主机:原理 + 双站点实战 + SELinux 排错
运维·自动化运维
mengge.cloud1 小时前
0909华为云网络类服务实践小白实验教程
linux·运维·服务器·网络·华为云·php
智恒百亿1 小时前
CSDN 文章|八卡 RTX5090 服务器深度实测:256GB 显存池,能否流畅跑通 70B 大模型微调?
运维·服务器
阿明61 小时前
基础编辑工具使用【Linux】
linux·运维·服务器
Tinyundg1 小时前
关于Termux的基本使用——安卓手机爆改Linux服务器?
linux·运维·服务器·智能手机·个人开发
AugustSkys2 小时前
PostgreSQL 完全指南:特性对比 + 安装部署 + 配置管理 + psql 实战 + pgAdmin 图形化
运维·postgresql·开源数据库·pgadmin
weixin_446260852 小时前
PromptMatic:通过多阶段提示优化提升大模型的指令遵循能力
运维·服务器
pt10432 小时前
从恐惧到自动化的百年突围
运维·自动化