10.1 核心概念
- SPA 部署(Single-Page Application)
- 前端打包成静态文件(React/Vue 的 dist),Nginx 发静态资源并用 try_files 回退到 index.html 支持前端路由。
- API 反代同域
- 把
/api/反代到后端服务,让前后端同域,从根本上规避跨域(CORS)问题,也统一了入口和 HTTPS。 - Docker 化 Nginx
- 用官方 nginx 镜像跑 Nginx,把配置和静态文件挂载或打包进镜像,实现环境一致、可复制部署。
- 多站点(Multi-tenant)
- 一台 Nginx 通过多个 server 块 + include 拆分,托管多个域名/项目,各自独立配置。
- 日志分析
- 从 access.log / error.log 中统计流量、状态码、慢请求,定位性能与故障——排障的第一手资料。
- 配置 checklist
- 上线前的核对清单:语法校验、TLS、安全头、限流、日志、reload 而非 restart,确保稳妥上线。
10.2 完整生产配置:SPA + API + HTTPS
# /etc/nginx/conf.d/app.conf
upstream api_backend {
server 127.0.0.1:3000;
keepalive 32;
}
# HTTP 只做跳转
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 主站
server {
listen 443 ssl;
http2 on;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_cache shared:SSL:10m;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
root /var/www/app/dist;
# API 反代(前后端同域,无 CORS)
location /api/ {
proxy_pass http://api_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;
}
# 带哈希指纹的静态资源,长缓存
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# SPA 路由回退
location / {
try_files $uri /index.html;
}
}
10.3 用 Docker 运行 Nginx
# Dockerfile —— 多阶段:构建前端 + 打进 Nginx 镜像
FROM node:20 AS build
WORKDIR /app
COPY . .
RUN npm ci && npm run build
FROM nginx:1.27-alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
# 官方镜像默认前台运行 nginx,无需 CMD
# 或直接挂载运行,改配置无需重建镜像
$ docker run -d --name web -p 80:80 \
-v $(pwd)/dist:/usr/share/nginx/html:ro \
-v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro \
nginx:1.27-alpine
# 改完配置后热重载容器内 Nginx
$ docker exec web nginx -s reload
容器里日志走标准输出
官方 nginx 镜像已把 access.log 软链到 /dev/stdout、error.log 到 /dev/stderr,日志直接进 docker logs 和日志采集系统。别再在容器里配写文件日志——那会让日志收集失灵。
10.4 多站点托管
# 每个项目一个文件,主配置统一 include
# /etc/nginx/conf.d/blog.conf、shop.conf、admin.conf ...
http {
include /etc/nginx/conf.d/*.conf;
}
# 各文件里各写各的 server 块,靠 server_name 区分
server { server_name blog.example.com; root /var/www/blog; }
server { server_name shop.example.com; root /var/www/shop; }
10.5 日志分析常用命令
# 访问量 Top 10 的 IP
$ awk '{print $1}' access.log | sort | uniq -c | sort -rn | head
# 各状态码分布
$ awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 找 5xx 错误请求
$ awk '$9 ~ /^5/' access.log | tail -20
# 实时盯错误日志
$ tail -f /var/log/nginx/error.log
10.6 上线配置 checklist
| 检查项 | 命令 / 说明 |
|---|---|
| 配置语法 | nginx -t 通过 |
| 用 reload 而非 restart | systemctl reload nginx |
| HTTPS 与跳转 | 80→443、证书有效、自动续期已装 |
| 安全头 | HSTS / X-Frame-Options / server_tokens off |
| 限流 | 登录、API 有 limit_req |
| gzip / 缓存头 | 文本压缩、静态资源长缓存 |
| 请求体上限 | client_max_body_size 匹配业务 |
| 日志 | access/error 正常写,或走 stdout |
| SPA 回退 | try_files 到 index.html 生效 |
10.7 常见故障排查
| 现象 | 可能原因与排查 |
|---|---|
| 502 Bad Gateway | 后端没起 / 端口错 / 崩溃。查后端进程、error.log、proxy_pass 地址 |
| 504 Gateway Timeout | 后端太慢。调大 proxy_read_timeout,或优化后端 |
| 404(SPA 刷新) | 缺 try_files 回退,加 try_files $uri /index.html; |
| 403 Forbidden | 文件权限 / autoindex 关 / deny 命中。查目录权限与 error.log |
| 413 请求体过大 | 调大 client_max_body_size |
| 改配置不生效 | 忘了 reload;或 nginx -t 没过沿用旧配置;或改动需 restart |
| CORS 报错 | 前后端未同域,用 /api/ 反代到同域即可根治 |
502 的头号嫌疑
看到 502 别急着改 Nginx——九成是后端本身没运行、崩溃或监听地址不对。第一步永远是确认后端进程健在(curl 127.0.0.1:3000 直连试试),再看 error.log 里 Nginx 报的 connect() failed 具体信息。
结课
从事件驱动架构,到 server/location 匹配、静态服务、反向代理、负载均衡、HTTPS、缓存、安全,再到这份完整的生产部署方案——你已经掌握了用 Nginx 搭建现代 web 入口所需的全部核心技能。剩下的,就是在真实项目里把它们用熟。
10.8 全课总结
- SPA 部署 = 静态资源 +
try_files $uri /index.html;/api/反代实现同域免 CORS。 - Docker 化用官方镜像,日志走 stdout,改配置
nginx -s reload热更新。 - 多站点靠 include + server_name 拆分;日志用 awk 快速分析。
- 上线走 checklist,永远
nginx -t后再 reload。 - 502 先查后端、504 调超时、SPA 404 补 try_files、CORS 用同域反代。