前后端项目部署路径与 Nginx 命名规范

前言

前后端分离项目在进入线上后,最常见的问题不是能不能跑,而是后续能不能稳定维护
很多团队在初期部署时随手放路径、随意写站点名,几个月后就会出现难排查、难交接、难扩容的问题。
本文给出一套实战可用的规范,覆盖部署目录结构、前后端路径划分、以及 Nginx 命名规则。
你可以直接按本文作为团队运维基线,再按业务规模逐步扩展。

目标

我们要解决三个关键问题。

  1. 前端静态资源和后端服务文件放在哪里。
  2. 多个环境和多个服务如何避免路径冲突。
  3. Nginx 配置文件、upstream、日志等如何统一命名。

路径规范

建议先约定一个统一根目录,例如 /srv/data
本文以 /srv 为例,按环境 + 项目 + 模块进行分层。
这样做的好处是目录一眼可读,自动化脚本也更容易编写。

/srv 在 Linux 目录语义里通常表示服务相关的数据根目录。
你可以把它理解为这台机器对外提供服务时使用的发布内容和业务目录
与之对比,/var 更偏向日志、缓存等经常变化的数据,/opt 更偏向第三方软件安装目录。

环境目录建议固定使用 devstagingprod 三层。

  1. dev 表示开发环境,主要用于开发自测和日常联调。
  2. staging 表示预发布环境,尽量贴近生产,用于上线前验收与回归测试。
  3. prod 表示生产环境,承载真实用户访问流量。

下面是推荐目录结构示例。
它适合大多数前后端分离项目,并支持多环境并行部署。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/srv
/prod
/myblog
/frontend
/web-admin
/releases
/current
/backend
/api-main
/releases
/current
/shared
/logs
/uploads
/scripts
/staging
/myblog
/frontend
/backend

这套结构里,releases 用于保留历史版本。
current 作为软链接指向当前生效版本,便于灰度或快速回滚。
shared 放跨版本共享的数据,例如上传文件和统一日志目录。

current 软链接示例

下面给出 current 软链接在真实发布中的常见操作。
建议把这些命令封装到发布脚本中,避免手工输入路径导致误操作。

这个示例先创建一个版本目录,并写入构建产物。
实际项目中你可以把 dist 替换成自己的打包目录。

1
2
mkdir -p /srv/prod/myblog/frontend/web-admin/releases/20260327-103000
cp -r dist/* /srv/prod/myblog/frontend/web-admin/releases/20260327-103000/

首次部署时,如果 current 不存在,可以直接创建软链接。
这样 Nginx 的 root 始终指向固定路径,而不是某个具体版本号目录。

1
ln -s /srv/prod/myblog/frontend/web-admin/releases/20260327-103000 /srv/prod/myblog/frontend/web-admin/current

后续发布新版本时,建议使用强制更新软链接的方式切换版本。
-sfn 可以在不改动 Nginx 配置的情况下,把 current 指向新版本目录。

1
ln -sfn /srv/prod/myblog/frontend/web-admin/releases/20260327-120000 /srv/prod/myblog/frontend/web-admin/current

如果新版本出现问题,可以快速把 current 切回上一个稳定版本。
切回后按需执行 nginx -tsystemctl reload nginx,即可完成回滚生效。

1
ln -sfn /srv/prod/myblog/frontend/web-admin/releases/20260327-103000 /srv/prod/myblog/frontend/web-admin/current

你还可以用下面命令确认软链接当前指向的真实目录。
在自动化脚本里,这一步常用于发布后自检。

1
readlink -f /srv/prod/myblog/frontend/web-admin/current

命名规范

命名的核心原则是可读、可检索、可自动化。
建议统一使用小写加中划线(kebab-case),避免空格和中文。
同一层级中,名称必须带有业务语义,不要使用 testnewfinal 这类临时词。

项目与服务命名

项目名建议使用 {business}-{system}
服务名建议使用 {domain}-{role},例如 api-mainapi-jobweb-admin
环境名固定为 devstagingprod,不要混用 onlineprd 等别名。

版本目录命名

版本目录建议使用时间戳或 CI 构建号。
例如 20260327-103000build-248
这样可以在故障时快速定位变更批次。

Nginx 规范

Nginx 规范建议同时覆盖配置文件命名、upstream 命名、server_name 规则和日志命名。
统一约定后,排障效率会显著提升。

多服务配置

多服务配置放在一起还是分开?

如果一个项目同时有接口服务、文件服务、前端站点,建议拆分为多个 Nginx 配置文件。
更推荐的粒度是 一类服务一个 server 配置文件一个域名一个配置文件
配置文件可以放在同一目录中统一管理,但内容应按服务边界分开维护。

这样做的直接收益是职责清晰,单次改动影响面更小。
接口服务改动不会误伤文件服务,前端路由改动也不会影响 API 转发。
线上出现故障时可以更快定位问题并执行单服务回滚。

下面是多服务拆分后的命名示例。
这些文件可以统一放在 /etc/nginx/conf.d/ 下,便于自动化发布脚本批量操作。

1
2
3
# /etc/nginx/conf.d/prod-myblog-web-80.conf
# /etc/nginx/conf.d/prod-myblog-api-80.conf
# /etc/nginx/conf.d/prod-myblog-file-80.conf

对应的 upstream 也建议按服务独立命名。
这样在跨文件排查链路时,可以快速确认每个域名实际转发到哪个后端服务。

1
2
3
4
5
6
7
upstream prod-myblog-api-upstream {
server 127.0.0.1:18080;
}

upstream prod-myblog-file-upstream {
server 127.0.0.1:18081;
}

小型项目在早期也可以把多个 location 暂时放在同一个 server 中。
但随着服务数量增加,建议尽早拆分,避免后期一次性重构风险。

配置文件命名

配置文件建议按环境 + 项目 + 模块 + 端口命名。
这样在 sites-enabled 中按名称就能快速识别用途。

1
2
# /etc/nginx/conf.d/prod-myblog-web-admin-80.conf
# /etc/nginx/conf.d/prod-myblog-api-user-8080.conf

文件名中建议避免下划线和缩写歧义。
例如优先使用 prod 而不是 p,使用 api-user 而不是 au

upstream 命名

upstream 名称建议与服务名强绑定,格式为 {env}-{project}-{service}-upstream
这样在跨文件排查时,能快速知道流量要转发到哪个后端。

1
2
3
4
upstream prod-myblog-api-user-upstream {
server 127.0.0.1:18080 max_fails=3 fail_timeout=30s;
keepalive 64;
}

upstream 不建议使用无语义的短名,例如 backendup1
服务一多后,这类名字几乎无法维护。

server_name 规则

域名建议按环境前缀 + 业务主域统一。
生产环境通常不加前缀,测试环境加 stagingdev 前缀。

1
2
3
4
server_name admin.myblog.com;
server_name api.myblog.com;
server_name staging-admin.myblog.com;
server_name staging-api.myblog.com;

如果你使用泛域名,也建议在注释中标明当前服务绑定关系。
避免后续误改导致流量串路由。

日志命名

日志文件建议包含环境、项目、服务、日志类型四段。
这样在日志平台或本机检索时更稳定。

1
2
access_log /var/log/nginx/prod-myblog-web-admin-access.log;
error_log /var/log/nginx/prod-myblog-web-admin-error.log warn;

错误日志级别建议按环境区分。
生产环境常用 warnerror,测试环境可临时提高到 info 辅助排查。

实现示例

下面给一个前端静态站点和后端 API 的典型 Nginx 片段。
你可以把它作为模板,再替换成自己的域名和端口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server {
listen 80;
server_name admin.myblog.com;

root /srv/prod/myblog/frontend/web-admin/current;
index index.html;

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

location /api/ {
proxy_pass http://prod-myblog-api-main-upstream/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

access_log /var/log/nginx/prod-myblog-web-admin-access.log;
error_log /var/log/nginx/prod-myblog-web-admin-error.log warn;
}

这个配置实现了前端 History 路由兜底。
同时把 /api/ 请求反向代理到后端 upstream。
部署时只需要更新 current 软链接,即可完成版本切换。

验证

发布后建议按下面步骤做最小验证。
先检查 Nginx 配置语法,再重载服务。
然后验证前端首页、前端路由、后端健康接口都可访问。

1
2
3
4
nginx -t
systemctl reload nginx
curl -I http://admin.myblog.com
curl -s http://api.myblog.com/health

如果出现 404,优先检查前端 roottry_files
如果出现 502,优先检查 upstream 目标端口和后端进程状态。

总结

一套稳定的运维规范,核心不在高深,而在统一并长期执行
你可以先落地三件事。

  1. 统一目录分层为环境 + 项目 + 模块
  2. 统一 Nginx 命名为环境 + 项目 + 服务 + 用途
  3. 统一发布流程为releases + current 软链接

当团队成员都遵循这套规则时,部署、回滚、排障都会明显更快。