Skip to content

Nginx 入门与部署

Nginx 是一个事件驱动的 Web 服务——一个 master 进程负责管理配置和控制 worker,多个 worker 进程负责接收连接、读取请求、匹配配置、返回响应或转发给后端。

text
nginx: master process /usr/sbin/nginx
├── nginx: worker process
├── nginx: worker process
└── nginx: worker process

一、几个核心概念

Nginx 的配置是分层的,每个层次有不同的职责:

概念做什么在配置的哪一层
master 进程管理进程,读取配置、控制 worker 的启停和 reload不由配置控制,Nginx 自身架构
worker 进程工作进程,实际处理客户端连接和请求worker_processes
server一个虚拟主机,按监听端口和域名区分server {}
location一个 URI 匹配规则,决定匹配后怎么处理location {}
upstream一组后端服务,反向代理和负载均衡时引用upstream {}

Nginx 最常见的三种形态:

形态处理方式例子
静态 Web 服务直接读取本机文件返回HTML、CSS、JS、图片、下载文件
反向代理入口把请求转发给后端应用Java、Go、Node.js、PHP-FPM
混合入口静态资源本机返回,API 转发后端/static/ 走文件,/api/ 走代理

混合形态在生产环境最常见:前端静态文件由 Nginx 直接返回(快),接口请求转发给后端(灵活)。排查时先确认请求进了哪个 server,命中了哪个 location,然后看它是在读文件还是转发。

二、安装

测试和普通生产环境用系统包最省事:

bash
# RHEL / Rocky / CentOS
yum install -y nginx
systemctl enable --now nginx
nginx -v

# Debian / Ubuntu
apt update
apt install -y nginx
systemctl enable --now nginx
nginx -v

常见路径(不同发行版可能有差异,用 rpm -ql nginxdpkg -L nginx 确认):

路径用途
/etc/nginx/nginx.conf主配置文件
/etc/nginx/conf.d/*.conf虚拟主机配置目录,主配置通过 include 引入
/usr/share/nginx/html包安装的默认静态文件目录
/var/log/nginx/access.log访问日志
/var/log/nginx/error.log错误日志
/usr/sbin/nginxNginx 主程序

三、配置文件结构

主配置 /etc/nginx/nginx.conf

nginx
user nginx;
worker_processes auto;     # 通常设为 CPU 核数,auto 自动检测

error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
    worker_connections 1024;  # 单个 worker 最多并发处理的连接数
}

http {
    include       /etc/nginx/mime.types;   # MIME 类型映射,决定 Content-Type
    default_type  application/octet-stream;

    access_log /var/log/nginx/access.log;

    sendfile on;              # 静态文件传输优化:直接内核态复制,不经过用户态
    keepalive_timeout 65;

    include /etc/nginx/conf.d/*.conf;  # 引入虚拟主机配置
}

配置上下文的层级关系:

上下文位置放什么
main最外层用户、worker 数、错误日志、pid
eventsevents {}worker 连接数等事件模型参数
httphttp {}HTTP 全局:日志格式、gzip、mime、include
serverserver {}虚拟主机:监听端口、域名、根目录
locationlocation {}URI 匹配后的行为:读文件、返回状态、转发代理

改完配置先检查语法:

bash
nginx -t        # 检查语法和引用文件是否存在

通过后 reload(不中断现有连接,旧 worker 处理完手中请求后退出,新 worker 用新配置):

bash
systemctl reload nginx

nginx -t 只看语法,不看逻辑——root 目录不存在它不会报错。还有一个常见的坑:主配置语法正确,但 conf.d 里某个 include 文件写错了,nginx -t 一样失败。

四、第一个静态站点

创建站点目录和测试文件:

bash
mkdir -p /data/www/example
echo 'hello nginx' > /data/www/example/index.html
chown -R nginx:nginx /data/www/example    # RHEL 系运行用户
# Debian/Ubuntu 运行用户是 www-data:
# chown -R www-data:www-data /data/www/example

虚拟主机配置 /etc/nginx/conf.d/example.conf

nginx
server {
    listen 80;
    server_name example.local;

    root /data/www/example;
    index index.html;

    location / {
        try_files $uri $uri/ =404;  # 依次尝试文件、目录,都不存在返回 404
    }

    access_log /var/log/nginx/example.access.log;
    error_log  /var/log/nginx/example.error.log warn;
}

加载并验证:

bash
nginx -t && systemctl reload nginx
curl -H 'Host: example.local' http://127.0.0.1/

返回 hello nginx 说明请求命中了这个 servercurl -H 'Host:' 是模拟浏览器带 Host 头的请求——Nginx 靠 Host 头匹配 server_name

五、静态资源和 API 混合

前后端分离应用最常见的配置:前端静态文件本机返回,接口请求转发给后端:

nginx
upstream app_api {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name app.example.local;

    root /data/www/app;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;  # SPA 路由:找不到文件时返回入口 HTML
    }

    location /static/ {
        expires 7d;                        # 静态资源让浏览器缓存 7 天
        try_files $uri =404;
    }

    location /api/ {
        proxy_pass http://app_api;         # 接口请求转给后端
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

try_files $uri $uri/ /index.html 是 SPA(单页应用)的标准写法——用户访问 /user/profile 时,服务器上没有这个文件,但前端路由需要 index.html 来接管这个路径。如果只是普通多页站点,用 try_files $uri $uri/ =404 就够了。

排查时的思路:静态资源 404 多半是目录路径和权限问题,API 502/504 多半是后端连接或响应问题。

六、虚拟主机

同一台 Nginx 可以跑多个站点,按 listen 端口和 Host 头区分:

nginx
server {
    listen 80;
    server_name app.example.local;
    root /data/www/app;
    location / {
        try_files $uri $uri/ =404;
    }
}

server {
    listen 80;
    server_name admin.example.local;
    root /data/www/admin;
    location / {
        try_files $uri $uri/ =404;
    }
}

验证不同域名:

bash
curl -H 'Host: app.example.local' http://127.0.0.1/
curl -H 'Host: admin.example.local' http://127.0.0.1/

没有匹配到 server_name 的请求会落到默认虚拟主机(第一个定义的 server,或显式标记 default_server 的那个)。建议显式写一个默认的拒绝站点,避免未知域名的探测请求打到真实业务:

nginx
server {
    listen 80 default_server;
    server_name _;
    return 444;    # Nginx 特有的状态码——直接关闭连接,不返回任何内容
}

七、location 匹配规则

location 决定一个 URI 怎么被处理。几种写法的优先级:

写法含义优先级
location = /health精确匹配,只有 /health 命中最高
location ^~ /static/前缀匹配,命中后不再检查正则高于正则
location ~ \.php$区分大小写的正则匹配按配置顺序
location ~* \.(jpg|png)$不区分大小写的正则匹配按配置顺序
location /api/普通前缀匹配最低,但选最长匹配

示例:

nginx
server {
    listen 80;
    server_name example.local;
    root /data/www/example;

    location = /health {
        return 200 "ok\n";     # 健康检查,直接返回文本
    }

    location ^~ /static/ {
        expires 7d;
        try_files $uri =404;
    }

    location / {
        try_files $uri $uri/ =404;
    }
}

rootalias 的差别:

nginx
location /static/ {
    root /data/www/example;    # /static/a.png → /data/www/example/static/a.png
}

location /assets/ {
    alias /data/cdn/;          # /assets/a.png → /data/cdn/a.png (location 前缀被替换)
}

root 是把 location 路径拼接在 root 目录后面;alias 是把 location 路径替换成 alias 目录。静态文件 404 时,先看 error_log 里 Nginx 实际去找的文件路径是什么——根据真实路径反推配置比猜要准。

八、常用命令

bash
nginx -t                         # 检查配置语法
nginx -T                         # 打印完整合并后的配置(include 展开后)
systemctl start nginx            # 启动
systemctl reload nginx           # 平滑重载配置(不中断连接)
systemctl restart nginx          # 重启(连接会断开)
systemctl stop nginx             # 停止
journalctl -u nginx -n 100 --no-pager
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

nginx -Tnginx -t 多一步——它不仅检查语法,还把 include 后的完整配置打印出来。排查"配置明明改了但好像没用"时,nginx -T 能发现是改错了文件还是被其他 include 覆盖了。

reloadrestart 的区别:reload 是平滑的——master 重新读配置,fork 新 worker,旧 worker 处理完手头请求后优雅退出,整个过程不掉连接。restart 是暴力的——直接停掉所有进程再启动,连接全断。改 LimitNOFILE 这类 systemd 级别的参数需要 restart,其他绝大多数情况用 reload。

九、常见启动问题

现象可能原因排查入口
nginx -t 失败配置语法错误、include 的文件不存在错误输出、nginx -T
端口被占用80/443 已被其他进程监听ss -lntp | grep ':80'
403 Forbidden目录权限不足、缺少 index 文件、被 deny 指令拦截error.log 会写具体原因
404 Not Foundroot/alias 路径不对、URI 匹配不对error.log 里的实际文件路径
访问到了默认站点Host 头没匹配到目标 server_namecurl -H 'Host:' 验证
reload 后配置没变reload 失败,旧 worker 仍在跑nginx -t 看新配置是否通过

排查思路顺着请求链路走:请求是否到达机器 → 是否命中正确的 server → 是否命中正确的 location → 最终是读文件还是转发。沿着这条线,比直接翻一堆配置更有效。