Appearance
Nginx 配置 - 前端应用部署与优化
1. Nginx 简介
1.1 什么是 Nginx
Nginx 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。它以事件驱动的异步架构闻名,能够处理大量并发连接。
核心特性:
- 高性能:事件驱动、异步非阻塞架构
- 反向代理:负载均衡、缓存、SSL 终止
- 静态文件服务:高效的文件服务能力
- URL 重写:灵活的路由规则
- Gzip 压缩:自动压缩响应内容
- 负载均衡:多种均衡策略
1.2 为什么使用 Nginx
优势:
- 性能优异:单机可处理数万并发
- 资源占用低:内存占用少,CPU 利用率高
- 配置灵活:强大的配置系统
- 高可用性:稳定可靠,支持热部署
- 丰富的模块:扩展功能丰富
1.3 适用场景
✓ 静态文件服务器
✓ 反向代理服务器
✓ 负载均衡器
✓ API 网关
✓ SSL/TLS 终止
✓ HTTP 缓存2. 安装与基础配置
2.1 安装 Nginx
Ubuntu/Debian
bash
# 更新包列表
sudo apt update
# 安装 Nginx
sudo apt install nginx
# 启动 Nginx
sudo systemctl start nginx
# 设置开机自启
sudo systemctl enable nginx
# 查看状态
sudo systemctl status nginxCentOS/RHEL
bash
# 安装 Nginx
sudo yum install nginx
# 启动服务
sudo systemctl start nginx
sudo systemctl enable nginxmacOS
bash
# 使用 Homebrew
brew install nginx
# 启动服务
brew services start nginx使用 Docker
bash
docker run -d \
--name nginx \
-p 80:80 \
-v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
-v $(pwd)/html:/usr/share/nginx/html:ro \
nginx:alpine2.2 目录结构
bash
# 主要目录
/etc/nginx/ # 配置文件目录
├── nginx.conf # 主配置文件
├── conf.d/ # 子配置文件目录
│ └── default.conf # 默认站点配置
├── sites-available/ # 可用站点配置
├── sites-enabled/ # 已启用站点配置
└── mime.types # MIME 类型定义
/var/log/nginx/ # 日志目录
├── access.log # 访问日志
└── error.log # 错误日志
/usr/share/nginx/html/ # 默认网站根目录
/var/www/html/ # 替代网站根目录2.3 基本命令
bash
# 测试配置
nginx -t
# 重新加载配置
nginx -s reload
# 停止服务
nginx -s stop
# 优雅停止
nginx -s quit
# 重新打开日志文件
nginx -s reopen
# 查看版本
nginx -v
nginx -V # 详细信息3. React 应用配置
3.1 基础 SPA 配置
nginx
# /etc/nginx/conf.d/react-app.conf
server {
listen 80;
server_name example.com www.example.com;
root /var/www/react-app;
index index.html;
# SPA 路由支持
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存
location /static {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}3.2 完整的生产配置
nginx
# /etc/nginx/conf.d/react-app.conf
server {
listen 80;
server_name example.com www.example.com;
# 重定向到 HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
# SSL 证书
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 网站根目录
root /var/www/react-app;
index index.html;
# 字符集
charset utf-8;
# 日志
access_log /var/log/nginx/react-app.access.log;
error_log /var/log/nginx/react-app.error.log;
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/rss+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
# SPA 路由
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# index.html 不缓存
location = /index.html {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# service-worker.js 不缓存
location = /service-worker.js {
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
add_header Expires "0";
}
# 安全 headers
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# CSP
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https://api.example.com;" always;
}3.3 多环境配置
nginx
# 开发环境
server {
listen 80;
server_name dev.example.com;
root /var/www/react-app-dev;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 开发环境允许 CORS
add_header Access-Control-Allow-Origin "*" always;
}
# 测试环境
server {
listen 80;
server_name staging.example.com;
root /var/www/react-app-staging;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# 基本认证保护
auth_basic "Staging Environment";
auth_basic_user_file /etc/nginx/.htpasswd;
}
# 生产环境(已在上面配置)4. 反向代理配置
4.1 代理到后端 API
nginx
server {
listen 80;
server_name example.com;
root /var/www/react-app;
# 前端路由
location / {
try_files $uri $uri/ /index.html;
}
# API 代理
location /api {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
# 代理 headers
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;
# WebSocket 支持
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
# 图片上传代理
location /upload {
client_max_body_size 10M;
proxy_pass http://localhost:3000/upload;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}4.2 负载均衡
nginx
# 定义上游服务器组
upstream backend {
# 负载均衡策略:轮询(默认)
server backend1.example.com:3000;
server backend2.example.com:3000;
server backend3.example.com:3000;
# 备用服务器
server backup.example.com:3000 backup;
# 健康检查
keepalive 32;
}
# IP Hash 策略
upstream backend_ip_hash {
ip_hash;
server backend1.example.com:3000;
server backend2.example.com:3000;
}
# 最少连接策略
upstream backend_least_conn {
least_conn;
server backend1.example.com:3000;
server backend2.example.com:3000;
}
# 权重策略
upstream backend_weighted {
server backend1.example.com:3000 weight=3;
server backend2.example.com:3000 weight=2;
server backend3.example.com:3000 weight=1;
}
server {
listen 80;
server_name example.com;
location /api {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}4.3 微服务路由
nginx
server {
listen 80;
server_name api.example.com;
# 用户服务
location /users {
proxy_pass http://user-service:8001;
proxy_set_header Host $host;
}
# 订单服务
location /orders {
proxy_pass http://order-service:8002;
proxy_set_header Host $host;
}
# 产品服务
location /products {
proxy_pass http://product-service:8003;
proxy_set_header Host $host;
}
# 支付服务
location /payments {
proxy_pass http://payment-service:8004;
proxy_set_header Host $host;
# 增加超时时间
proxy_read_timeout 120s;
}
}5. 缓存配置
5.1 静态资源缓存
nginx
server {
listen 80;
server_name example.com;
root /var/www/react-app;
# 长期缓存的资源
location ~* \.(jpg|jpeg|png|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# CSS 和 JS 文件
location ~* \.(css|js)$ {
expires 1M;
add_header Cache-Control "public, max-age=2592000";
}
# 字体文件
location ~* \.(woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Access-Control-Allow-Origin "*";
}
# HTML 文件不缓存
location ~* \.html$ {
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
}5.2 代理缓存
nginx
# 缓存路径配置
proxy_cache_path /var/cache/nginx/api
levels=1:2
keys_zone=api_cache:10m
max_size=1g
inactive=60m
use_temp_path=off;
server {
listen 80;
server_name example.com;
location /api {
proxy_pass http://backend;
# 启用缓存
proxy_cache api_cache;
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
# 缓存键
proxy_cache_key "$scheme$request_method$host$request_uri";
# 缓存控制
proxy_cache_bypass $http_cache_control;
add_header X-Cache-Status $upstream_cache_status;
# 过期后在后台更新
proxy_cache_background_update on;
proxy_cache_revalidate on;
# 使用过期缓存
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
# 锁定
proxy_cache_lock on;
proxy_cache_lock_timeout 5s;
}
}5.3 FastCGI 缓存
nginx
fastcgi_cache_path /var/cache/nginx/fastcgi
levels=1:2
keys_zone=fastcgi_cache:100m
inactive=60m;
server {
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_index index.php;
# 启用 FastCGI 缓存
fastcgi_cache fastcgi_cache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
add_header X-FastCGI-Cache $upstream_cache_status;
}
}6. SSL/TLS 配置
6.1 基础 HTTPS 配置
nginx
server {
listen 443 ssl http2;
server_name example.com;
# SSL 证书
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# SSL 协议
ssl_protocols TLSv1.2 TLSv1.3;
# SSL 密码套件
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
# SSL 会话
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
root /var/www/react-app;
location / {
try_files $uri $uri/ /index.html;
}
}6.2 Let's Encrypt 配置
nginx
server {
listen 80;
server_name example.com www.example.com;
# ACME 挑战
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/letsencrypt;
}
# 其他请求重定向到 HTTPS
location / {
return 301 https://$server_name$request_uri;
}
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 其他配置...
}bash
# 获取证书
certbot certonly --webroot \
-w /var/www/letsencrypt \
-d example.com \
-d www.example.com
# 自动续期
certbot renew --dry-run6.3 OCSP Stapling
nginx
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/nginx/ssl/ca-certs.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
}7. 性能优化
7.1 连接优化
nginx
# 全局配置
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# TCP 优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# 超时设置
keepalive_timeout 65;
keepalive_requests 100;
client_header_timeout 12;
client_body_timeout 12;
send_timeout 10;
# 缓冲区大小
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
}7.2 压缩优化
nginx
http {
# Gzip 压缩
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/rss+xml
font/truetype
font/opentype
application/vnd.ms-fontobject
image/svg+xml;
# Brotli 压缩(需要安装模块)
brotli on;
brotli_comp_level 6;
brotli_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss;
}7.3 缓冲和限制
nginx
http {
# 连接限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn addr 100;
# 请求速率限制
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
limit_req zone=one burst=20 nodelay;
# 文件缓存
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}8. 安全配置
8.1 基础安全
nginx
server {
# 隐藏 Nginx 版本
server_tokens off;
# 禁止访问隐藏文件
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# 禁止执行 PHP
location ~* \.(php|phtml)$ {
deny all;
}
# 限制请求方法
if ($request_method !~ ^(GET|HEAD|POST)$ ) {
return 405;
}
# 防止点击劫持
add_header X-Frame-Options "SAMEORIGIN" always;
# XSS 保护
add_header X-XSS-Protection "1; mode=block" always;
# MIME 类型嗅探保护
add_header X-Content-Type-Options "nosniff" always;
}8.2 访问控制
nginx
server {
# IP 白名单
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
try_files $uri $uri/ /index.html;
}
# 基本认证
location /private {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
try_files $uri $uri/ /index.html;
}
# 地理位置限制
location / {
if ($geoip_country_code ~ (CN|US|GB)) {
return 403;
}
}
}8.3 防 DDoS
nginx
http {
# 连接限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
limit_conn_zone $server_name zone=perserver:10m;
# 请求限制
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=5r/s;
server {
# 应用限制
limit_conn addr 10;
limit_conn perserver 1000;
limit_req zone=req_limit_per_ip burst=10 nodelay;
# 超时保护
client_body_timeout 10s;
client_header_timeout 10s;
# 慢速攻击防护
send_timeout 10s;
}
}9. 日志管理
9.1 日志配置
nginx
http {
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# JSON 日志格式
log_format json escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time"'
'}';
# 访问日志
access_log /var/log/nginx/access.log main;
# 错误日志级别
error_log /var/log/nginx/error.log warn;
server {
# 站点特定日志
access_log /var/log/nginx/example.com.access.log json;
error_log /var/log/nginx/example.com.error.log;
# 禁用特定 location 的日志
location /health {
access_log off;
return 200 "OK\n";
}
}
}9.2 日志轮转
bash
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}10. 监控和调试
10.1 状态监控
nginx
server {
listen 8080;
server_name localhost;
# Nginx 状态
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
# 健康检查
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}10.2 调试配置
nginx
# 启用调试日志
error_log /var/log/nginx/debug.log debug;
server {
# 调试特定请求
location /api {
error_log /var/log/nginx/api-debug.log debug;
proxy_pass http://backend;
}
}11. Docker 中的 Nginx
11.1 Dockerfile
dockerfile
FROM nginx:alpine
# 复制配置文件
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
# 复制静态文件
COPY dist/ /usr/share/nginx/html/
# 暴露端口
EXPOSE 80 443
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]11.2 docker-compose.yml
yaml
version: '3.8'
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./conf.d:/etc/nginx/conf.d:ro
- ./dist:/usr/share/nginx/html:ro
- ./ssl:/etc/nginx/ssl:ro
restart: unless-stopped
networks:
- app-network
networks:
app-network:
driver: bridge12. 最佳实践
12.1 配置组织
bash
# 模块化配置结构
/etc/nginx/
├── nginx.conf # 主配置
├── conf.d/ # 站点配置
│ ├── example.com.conf
│ └── api.example.com.conf
├── snippets/ # 可复用配置片段
│ ├── ssl-params.conf
│ ├── security-headers.conf
│ └── gzip.conf
└── sites-available/ # 可用站点
└── sites-enabled/ # 已启用站点nginx
# snippets/security-headers.conf
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# 在主配置中引用
server {
include snippets/security-headers.conf;
}12.2 性能检查清单
- [ ] 启用 Gzip 压缩
- [ ] 配置静态资源缓存
- [ ] 使用 HTTP/2
- [ ] 启用 keepalive
- [ ] 优化 worker 进程数
- [ ] 配置代理缓存
- [ ] 使用 sendfile
- [ ] 调整缓冲区大小
12.3 安全检查清单
- [ ] 隐藏 Nginx 版本号
- [ ] 配置 SSL/TLS
- [ ] 添加安全 headers
- [ ] 限制请求速率
- [ ] 配置访问控制
- [ ] 禁止访问敏感文件
- [ ] 使用最新版本
13. 故障排除
13.1 常见问题
bash
# 配置测试失败
nginx -t # 查看详细错误信息
# 端口被占用
sudo lsof -i :80
sudo netstat -tuln | grep :80
# 权限问题
sudo chown -R www-data:www-data /var/www/
sudo chmod -R 755 /var/www/
# 日志查看
tail -f /var/log/nginx/error.log
tail -f /var/log/nginx/access.log13.2 性能调优
bash
# 查看连接数
netstat -an | grep :80 | wc -l
# 查看进程状态
ps aux | grep nginx
# 监控资源使用
top -p $(pgrep nginx | tr '\n' ',' | sed 's/,$//')14. 总结
Nginx 为前端应用提供了:
- 高性能服务:静态文件服务和反向代理
- 灵活配置:丰富的配置选项
- 安全保障:SSL/TLS、访问控制、安全 headers
- 缓存优化:多层缓存策略
- 负载均衡:多种均衡算法
通过合理配置 Nginx,可以显著提升应用的性能和安全性。