Nginx 通过 map 指令结合 $host、请求头或路径前缀定义环境变量,再在 location 中用 proxy_pass 或 alias 动态路由至对应后端或静态资源路径,实现多环境配置。

在 Nginx 中,location 本身不直接支持“多环境配置”的动态切换(比如开发/测试/生产自动适配),但可以通过 请求特征识别 + 变量 + rewrite 或 proxy_pass 动态拼接 实现路径的环境感知路由。核心思路是:把环境标识(如域名、请求头、URL 路径前缀)映射为变量,再用该变量控制后端目标地址或静态资源路径。
用 $host 或自定义请求头识别环境
最常用且可靠的方式是依据域名区分环境。例如:
- dev.example.com → 指向本地开发服务(127.0.0.1:3000)
- test.example.com → 指向测试服务器(10.0.1.10:8080)
- example.com → 指向生产集群(upstream prod_backend)
实现方式是在 server 块中用 map 指令预定义后端地址变量:
map $host $backend_addr {
default "prod_backend";
~^dev\. "127.0.0.1:3000";
~^test\. "10.0.1.10:8080";
}
server {
listen 80;
server_name dev.example.com test.example.com example.com;
location /api/ {
proxy_pass http://$backend_addr;
proxy_set_header Host $host;
}
}
用 URL 路径前缀做环境标记(适合单域名场景)
如果所有环境都走同一个域名(如 example.com/dev/...),可用 location 匹配前缀并重写路径:
- /dev/api/ → 代理到开发后端,同时去掉
/dev前缀 - /test/api/ → 代理到测试后端,同样剥离前缀
示例配置:
location ^~ /dev/api/ {
rewrite ^/dev(/api/.*) $1 break;
proxy_pass http://127.0.0.1:3000;
}
location ^~ /test/api/ {
rewrite ^/test(/api/.*) $1 break;
proxy_pass http://10.0.1.10:8080;
}
location /api/ {
proxy_pass http://prod_backend;
}
注意:^~ 优先级高于正则,确保前缀匹配不被后续正则 location 干扰;rewrite ... break 是关键,它让 proxy_pass 使用修改后的 URI。
结合 cookie 或 header 实现灰度或调试路由
对需要临时切环境的调试场景,可读取请求中的自定义 header(如 X-Env-Target: dev)或 cookie:
map $http_x_env_target $route_to {
default "prod_backend";
"dev" "127.0.0.1:3000";
"test" "10.0.1.10:8080";
}
server {
location /api/ {
proxy_pass http://$route_to;
}
}
这样前端发请求时带上 X-Env-Target: dev,Nginx 就会自动路由过去,无需改域名或路径,适合 QA 或联调使用。
静态资源也支持按环境加载不同版本
不只是 API,前端 JS/CSS 等静态资源也能按环境提供不同路径或版本。例如:
- dev 环境加载未压缩、带 sourcemap 的资源(/static/dev/app.js)
- prod 环境加载 CDN 上的压缩版(https://cdn.example.com/v2.3.1/app.min.js)
可通过 alias 或 root 配合变量实现:
map $host $static_root {
~^dev\. "/var/www/dev";
~^test\. "/var/www/test";
default "/var/www/prod";
}
location /static/ {
alias $static_root/static/;
}
不复杂但容易忽略:所有动态变量必须在 server 或 http 块顶层用 map 定义,不能在 location 内直接赋值;proxy_pass 后不能跟 URI(如 proxy_pass http://x:8080/)时,才允许 rewrite 修改路径;否则 rewrite 无效。


















