切换日光/暗黑模式
005. 后端发版与网络安全边界
学习目标
这一节把后端项目部署到服务器,并补齐部署脚本、代码拉取、端口访问和安全边界的理解。
学完后,你应该能理解:
- 服务器上拉代码为什么推荐使用 SSH Key;
- 生产环境
.env和本地.env为什么不一样; - 为什么生产数据库端口不应该一直对公网开放;
- 容器内部端口、宿主机端口、防火墙端口分别是什么;
- 后端发版脚本大概做了哪些事;
- 前端、后端、静态资源为什么要统一访问入口。
后端发版脚本负责什么?
后端发版脚本不是神秘工具,本质上就是把一系列部署命令固定下来。
它通常会做这些事:
- 进入后端项目目录;
- 如果没有代码,就从仓库 clone;
- 如果已有代码,就拉取最新代码;
- 准备生产环境
.env; - 激活 Python / Conda 环境;
- 安装或更新依赖;
- 重启后端服务;
- 输出运行状态。
对只写过 JS 的同学来说,可以把它理解成把手动部署步骤写成一个脚本,类似把多个 pnpm install、pnpm build、pm2 restart 组合起来。
用 SSH Key 拉代码
服务器要从代码仓库拉代码,有两种常见方式:
| 方式 | 特点 |
|---|---|
| HTTPS + 账号密码 / Token | 配置简单,但权限和凭据管理更麻烦 |
| SSH Key | 更适合服务器部署,权限可单独控制 |
课程里更推荐用 SSH Key。
基本思路是:
- 在服务器上生成 SSH Key;
- 打印公钥内容;
- 把公钥添加到代码仓库的部署 Key 里;
- 服务器以后就能用 SSH 协议拉代码。
这样做的好处是:如果某台服务器以后不用了,只要删除对应部署 Key,这台服务器就不能再拉仓库代码。
~ 是什么?
Linux 里经常看到 ~。
它表示当前用户的家目录。
如果当前登录用户是 root,那么:
bash
~通常对应:
bash
/root所以类似下面的路径:
bash
~/.ssh/id_rsa.pub可以理解成当前用户家目录里的 SSH 公钥文件。
本地 .env 和生产 .env
本地开发环境和服务器生产环境的 .env 不一样。
本地开发时,你的后端代码跑在自己电脑上,但数据库、Redis、Milvus 可能连的是远程服务器:
txt
本地后端 -> 远程服务器数据库生产环境里,后端代码也部署在服务器上,数据库服务也在同一台服务器上:
txt
服务器后端 -> 服务器本机数据库所以生产 .env 里很多 Host 可以写成本机地址,例如 localhost 或容器网络里的服务名,而不是公网 IP。
生产环境不要暴露数据库端口
前面为了本地调试,可能把 MariaDB、PostgreSQL、Redis、Milvus 的端口放到了云服务器防火墙里。
但生产环境下,数据库端口不应该长期对公网开放。
原因很简单:
- 数据库里有业务数据;
- 端口暴露后会被扫描;
- 密码弱或配置错误会有风险;
- 真实企业里通常只允许内网访问数据库。
部署完成后,后端和数据库都在服务器内部,后端访问数据库不需要经过公网防火墙。公网只需要暴露 Web 入口即可。
容器端口、宿主机端口、防火墙端口
端口问题最容易混。
可以按三层理解:
| 层级 | 例子 | 说明 |
|---|---|---|
| 容器内部端口 | MariaDB 内部 3306 | 数据库程序自己监听的端口 |
| 宿主机映射端口 | 服务器 14148 | Docker 把外部请求转到容器内部 |
| 云防火墙端口 | 是否放开 14148 | 决定公网能不能访问这个端口 |
如果两个 MariaDB 容器内部都用 3306,没问题。只要宿主机映射端口不同即可,例如:
txt
服务器 14148 -> 容器 A 3306
服务器 14149 -> 容器 B 3306外部连接时,关注的是服务器映射出来的端口,不是容器内部端口。
内部访问不走公网防火墙
当后端和数据库都在同一台服务器里时,后端访问数据库属于服务器内部通信。
这种访问不会从公网绕一圈,也不会被云服务器公网防火墙拦截。
这就是为什么生产环境可以关闭数据库公网端口:
- 本地电脑不能直接连数据库;
- 服务器内部后端仍然可以连数据库;
- 外部用户只访问前端和后端 API。
前端为什么不在服务器上打包?
前端打包很吃内存。
课程里购买的学习服务器内存有限,同时已经部署了很多数据库和工具服务。如果再在服务器上跑前端构建,很容易把内存打满。
所以更合理的方式是:
- 在本地电脑打包前端;
- 生成静态资源;
- 上传到服务器;
- 由 Nginx / 宝塔站点托管这些静态文件。
这和很多公司里的 CI/CD 思路类似:构建和运行不一定发生在同一台机器上。
前端、后端、静态资源的访问入口
一个完整 Web 项目通常至少有三类资源:
- 前端页面;
- 后端 API;
- 图片、文件、发票等静态资源。
如果它们分别用不同端口访问,例如:
txt
前端:http://IP:80
后端:http://IP:7003
静态资源:http://IP:8080浏览器会遇到跨域问题,用户访问也不方便。
更理想的方式是只给外部一个统一入口:
txt
http://IP然后由 Nginx 根据路径转发:
txt
/ -> 前端页面
/api -> 后端服务
/upload -> 静态资源这样用户只需要记住一个 IP 或一个域名。
跨域不是靠“放开所有”解决
开发阶段为了方便,后端可能允许所有来源跨域访问。
但生产环境不应该随便允许所有网站请求你的后端接口。
更好的方向是:
- 让前端、后端、静态资源尽量走同源入口;
- 通过 Nginx 统一协议、域名或 IP、端口;
- 后端生产配置里减少跨域放开范围;
- 只允许自己的前端访问自己的后端。
跨域问题不是简单报错,而是浏览器安全模型的一部分。后面部署前端和 Nginx 时会继续处理它。