什么是 Nginx?它有什么作用?
Nginx是一款高性能的 HTTP 服务器 和 反向代理服务器,同时支持 IMAP/POP3/SMTP 邮件代理。它在高并发场景下表现极其出色,是当今互联网架构中不可或缺的核心组件。
Nginx 的主要用途
| 应用场景 | 说明 |
|---|---|
| 静态资源服务 | 高效托管 HTML/CSS/JS/图片等静态文件 |
| 反向代理 | 将请求转发到后端应用服务器(如 Tomcat、Node.js) |
| 负载均衡 | 在多个后端服务器之间分发流量 |
| HTTPS 终结 | 统一管理 SSL/TLS 证书,解密后转发明文到内部服务 |
| API 网关 | 限流、鉴权、日志、请求过滤等前置处理 |
环境准备:WSL + Docker
本系列教程从 零基础 开始,记录我的 Nginx 从入门到精通的学习过程。第一步是搭建一个可复现的实验环境。
- WSL(Windows Subsystem for Linux):在 Windows 上运行 Linux 的轻量级虚拟化方案
- Docker:容器化平台,让我们快速启动/销毁 Nginx 实例而不污染宿主机
为什么不在 Windows 上直接装 Nginx? Nginx 是 Linux 生态下的产物,许多核心特性依赖 Linux 内核——比如
sendfile零拷贝、epoll高并发模型、user用户切换等。Windows 版 Nginx 不支持这些特性,性能差异很大,通常仅用于快速测试。所以本教程使用 WSL + Docker,让 Nginx 跑在 Linux 内核之上,获得与生产环境一致的表现。
确保你的 WSL 中已安装 Docker,可通过
docker --version验证。
Docker Compose 配置
创建项目目录结构:
nginx-learning/
├── docker-compose.yml
├── nginx.conf
├── conf.d/
│ └── default.conf
├── html/
│ └── index.html
└── logs/
docker-compose.yml
services:
nginx:
image: nginx:latest # 使用官方最新镜像
container_name: nginx-learning
ports:
- "8080:80" # 将宿主机的 8080 映射到容器的 80 端口
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro # 主配置文件(只读)
- ./conf.d:/etc/nginx/conf.d:ro # 站点配置目录(只读)
- ./html:/usr/share/nginx/html:ro # 静态文件目录(只读)
- ./logs:/var/log/nginx # 日志目录(可写)
restart: unless-stopped # 除非手动停止,否则自动重启
数据卷目录参考
| 宿主机路径 | 容器内路径 | 说明 |
|---|---|---|
./nginx.conf | /etc/nginx/nginx.conf | 主配置文件 |
./conf.d/ | /etc/nginx/conf.d/ | 站点配置(可包含多个 site) |
./html/ | /usr/share/nginx/html | 静态文件目录 |
./logs/ | /var/log/nginx | 访问日志和错误日志 |
Nginx 最小化配置解析
以下是生产环境可用的精简配置,每行都有其存在的意义:
user nginx; # 工作进程以 nginx 用户身份运行(安全)
worker_processes auto; # 自动匹配 CPU 核心数
error_log /var/log/nginx/error.log warn; # 错误日志级别:warn 及以上
pid /var/run/nginx.pid; # 主进程 PID 文件
events {
worker_connections 1024; # 每个工作进程最大并发连接数
}
http {
include /etc/nginx/mime.types; # MIME 类型映射
default_type application/octet-stream; # 未识别文件类型的默认处理
# 自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main; # 访问日志使用 main 格式
sendfile on; # 启用零拷贝文件传输(大幅提升静态文件性能)
keepalive_timeout 65; # 长连接超时时间(秒)
# 引入所有自定义站点配置
include /etc/nginx/conf.d/*.conf;
}
关键参数解析
| 参数 | 作用 |
|---|---|
user nginx; | 工作进程以 nginx 用户身份运行,遵循最小权限原则(见下文详解) |
worker_processes auto | Nginx 会为每个 CPU 核心创建一个工作进程,一个核心对应一个 worker 进程是最优选择,过多会导致上下文切换降低性能 |
worker_connections 1024 | 一个工作进程最多同时处理 1024 个连接,总并发 = worker_processes × 1024 |
sendfile on | 零拷贝技术,数据直接从文件到网卡,不经过用户态,性能提升显著 |
keepalive_timeout 65 | 客户端长连接保持时间,减少 TCP 三次握手开销 |
error_log /var/log/nginx/error.log warn | 错误日志,记录 warn 级别及以上的运行异常,用于问题排查 |
access_log /var/log/nginx/access.log main | 访问日志,以 main 格式记录所有客户端请求详情 |
include /etc/nginx/mime.types | 引入 MIME 类型映射表,让 Nginx 能根据文件后缀(如 .css、.js)正确设置响应头中的 Content-Type,否则浏览器会把样式文件和脚本当成二进制流下载 |
default_type application/octet-stream | 当文件后缀不在 mime.types 中时使用的默认类型,作为兜底 |
工作进程用户说明
user nginx; 定义了 Nginx 工作进程以哪个操作系统用户身份运行。
⚠️ 这里的
nginx就是 Linux 系统中的一个真实用户账号,不是 Nginx 特有的概念。可以用以下命令查看它是否存在:id nginx # 输出示例:uid=101(nginx) gid=101(nginx) groups=101(nginx) grep nginx /etc/passwd # 输出示例:nginx:x:101:101:nginx user:/var/cache/nginx:/sbin/nologin同理,如果改为
user www-data;,系统中就必须存在www-data这个用户。本质上这就是告诉操作系统:"让 Nginx 的工作进程以这个 Linux 用户的身份运行",所有文件的读写权限都受该用户权限的约束。
为什么工作进程不能是 root?
Nginx 启动后会创建两类进程:
| 进程 | 运行身份 | 职责 |
|---|---|---|
| master process(主进程) | root | 读取配置、绑定端口(80/443 需要 root 权限)、管理工作进程 |
| worker process(工作进程) | 普通用户(由 user 指定) | 处理实际的客户端请求——接收请求、读取文件、返回响应 |
所有客户端流量都由工作进程处理。如果用 root 运行工作进程,一旦 Nginx 出现安全漏洞,攻击者就能获得 root 权限。降权到普通用户是 最小权限原则 的体现。
可取值及区别
# 语法:user <用户名> [<用户组>];
user nginx; # 官方 Docker 镜像默认,镜像内已创建该用户
user www-data; # Debian/Ubuntu 系统安装 nginx 时的默认值
user nobody; # 几乎所有系统都有的通用低权限账户
user www www; # 指定用户名为 www,用户组也为 www
实际选哪个取决于三点:
- 静态文件权限 — 工作进程必须能读取静态文件、写入日志目录。如果用
user nobody但文件权限设为 600 且归 root 所有,就会返回 403 - 发行版惯例 — 每种 nginx 打包方式有固定选择:官方 Docker 镜像用
nginx,Ubuntu/Debian 用www-data,CentOS 用nginx - 自定义编译 — 如果源码编译安装,默认值为
nobody,可通过编译参数修改
如果要修改工作进程用户,需确保目标用户对
html/有读权限、对logs/有写权限。在 docker-compose 场景中,由于镜像已预制好nginx用户和对应权限,直接使用user nginx;即可。
日志文件说明
Nginx 主要产生以下两类日志文件,存储在 ./logs/ 目录中:
| 日志文件 | 类型 | 作用说明 |
|---|---|---|
access.log | 访问日志 | 记录每一次客户端请求的详细信息,包括 IP、时间、请求方法、URL、状态码、响应大小、浏览器标识等。用于流量分析、请求溯源、安全审计 |
error.log | 错误日志 | 记录 Nginx 运行过程中的错误和警告,如配置加载失败、连接超时、后端服务不可用等。日志级别从低到高:debug → info → notice → warn → error → crit → alert → emerg,级别越高记录越少 |
本文配置的访问日志使用了 main 自定义格式,各字段含义如下:
| 字段 | 变量 | 说明 |
|---|---|---|
| 客户端 IP | $remote_addr | 发起请求的客户端地址 |
| 客户端用户 | $remote_user | HTTP 基本认证的用户名 |
| 请求时间 | $time_local | 服务器本地时间 |
| 请求行 | $request | 请求方法 + URI + HTTP 协议版本 |
| 状态码 | $status | HTTP 响应状态码(如 200、404、502) |
| 响应大小 | $body_bytes_sent | 响应体字节数 |
| 来源页面 | $http_referer | 请求来源 URL |
| 用户代理 | $http_user_agent | 客户端浏览器/爬虫标识 |
| 真实 IP | $http_x_forwarded_for | 经过代理链后的真实客户端 IP |
实践建议:排错时先看
error.log定位错误类型,再用access.log分析请求模式。可配合tail -f logs/access.log实时监控请求。
sendfile 说明
sendfile on; 启用的是 Linux 内核的零拷贝(zero-copy) 技术,专门优化静态文件传输性能。
传统方式(sendfile off):
磁盘 ──→ 内核缓冲区 ──→ 用户态(Nginx 进程) ──→ 内核缓冲区 ──→ 网卡
↑__________________↑
数据从内核拷贝到用户态,再从用户态拷回内核
sendfile 方式(sendfile on):
磁盘 ──→ 内核缓冲区 ──→ 网卡
↑________↑
数据全程在内核态传递,不经过用户态,CPU 不参与搬运
对比:
| 传统方式 | sendfile 零拷贝 | |
|---|---|---|
| 数据拷贝次数 | 2 次(内核→用户→内核) | 1 次(内核→网卡) |
| 上下文切换 | 2 次(用户态/内核态切换) | 1 次 |
| CPU 负载 | CPU 参与内存拷贝,高负载下消耗明显 | CPU 几乎不参与,纯 DMA 传输 |
适用场景:托管静态文件(HTML/CSS/JS/图片)时效果显著。反向代理到后端服务的场景不适用,因为数据来自后端 socket 而非磁盘文件。
Server 块配置(虚拟主机)
站点配置放置在 conf.d/ 目录下,Nginx 通过 include 指令自动加载所有 .conf 文件:
server {
listen 80; # 监听端口
server_name localhost; # 域名匹配(可替换为你的域名)
location / {
root /usr/share/nginx/html; # 站点根目录
index index.html index.htm; # 默认首页文件
}
# 可添加更多 location 用于学习
# location /api/ {
# proxy_pass http://backend:3000; # 反向代理示例
# }
}
location 匹配规则
这是 Nginx 最核心也是最灵活的部分,优先级从高到低:
| 匹配方式 | 示例 | 优先级 |
|---|---|---|
| 精确匹配 | = /favicon.ico | 最高 |
| 前缀匹配(^~) | ^~ /static/ | 高 |
| 正则匹配(~) | ~ \.php$ | 中 |
| 普通前缀 | /api/ | 低 |
| 默认匹配 | / | 最低 |
静态页面示例
创建一个简单的 HTML 页面来验证环境是否正常运行:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nginx Learning</title>
</head>
<body>
<h1>Hello, Nginx!</h1>
<p>This is your learning environment.</p>
<p>当前时间:<span id="time"></span></p>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
</script>
</body>
</html>
启动与访问验证
# 启动所有服务(-d 表示后台运行)
docker compose up -d
# 查看容器状态
docker compose ps
# 查看实时日志
docker compose logs -f nginx
# 停止服务
docker compose down
启动后访问:http://localhost:8080/
✅ 如果看到 "Hello, Nginx!" 页面,说明环境搭建成功!
总结
通过本教程,你已经完成了 Nginx 学习环境的搭建,并掌握了:
- ✅ Nginx 的核心应用场景
- ✅ Docker Compose 编排 Nginx 容器
- ✅ nginx.conf 主配置文件的结构与关键参数
- ✅ server 块和 location 匹配规则
- ✅ 静态站点部署与访问验证