Nginx 学习笔记:Server 块配置详解,域名路由与多站点部署实战


📝 本文首发于 栏轩·阁

欢迎访问阅读原文,获取更好的阅读体验。


什么是 Server 块?

在 Nginx 中,Server 块 (也叫做虚拟主机配置)是路由分发的基础单元。Nginx 通过 listen 和 server_name 两个关键参数,决定每个请求该由哪个 Server 块处理,从而实现一台服务器托管多个网站。

可以把 Server 块想象成 Nginx 内部的"虚拟服务器"------每个 Server 块独立配置自己的域名、端口、根目录和路由规则,互不干扰。

一、基础配置:listen + server_name

最基本的 Server 块配置如下:

nginx 复制代码
server {
    listen       80;             # 监听端口
    server_name  localhost;      # 域名匹配

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

listen ------ 监听端口

写法 说明
listen 80; 监听 IPv4 的 80 端口
listen [::]:80; 监听 IPv6 的 80 端口
listen 8080; 监听非标准端口(如 8080)
listen 443 ssl; 监听 HTTPS 端口并启用 SSL
listen 80 default_server; 设为默认服务器,当没有匹配时使用

server_name ------ 域名匹配

server_name 匹配的是请求头中的 Host 字段 。浏览器访问 http://example.com 时,请求头中会携带 Host: example.com,Nginx 拿这个值与所有 Server 块的 server_name 对比,找到对应的处理规则。

可以在浏览器开发者工具 → 网络面板中查看每个请求的 Host 请求头。

二、请求路由流程

当一个请求到达 Nginx 时,匹配顺序如下:

复制代码
客户端请求 ──→ 根据 listen 端口找到 Server 块列表
                       │
                       ▼
               根据 server_name 匹配 Host 请求头
                       │
            ┌──────────┼──────────┐
            ▼          ▼          ▼
         精确匹配   通配符匹配   正则匹配
                       │
                       ▼
               进入对应的 Server 块
                       │
                       ▼
               继续匹配 location 路由

如果所有 server_name 都没有匹配到,Nginx 会使用该端口上第一个 Server 块(或标记了 default_server 的那个)来处理请求。

三、多域名实战

场景

假设我们有一个 Nginx,想同时托管两个网站:

  • blog.com ------ 博客站点,首页为 blog 页面
  • login.com ------ 登录站点,首页为 login 页面

第一步:修改 hosts 文件

由于本机没有真实的域名解析,需要在本机的 hosts 文件中添加域名映射,把两个域名指向本地:

bash 复制代码
# Windows: C:\Windows\System32\drivers\etc\hosts
# Linux/macOS: /etc/hosts

127.0.0.1  blog.com
127.0.0.1  login.com

修改 hosts 后在 Windows 上需要刷新 DNS 缓存才能生效:

bash 复制代码
ipconfig /flushdns

这样访问 blog.com 和 login.com 就会解析到本机。

第二步:准备站点目录

复制代码
nginx-learning/
├── conf.d/
│   ├── blog.conf          # blog.com 配置
│   └── login.conf         # login.com 配置
├── html/
│   ├── blog/
│   │   └── index.html     # blog 站点首页
│   └── login/
│       └── index.html     # login 站点首页
└── docker-compose.yml

第三步:Nginx 配置

blog.conf:

nginx 复制代码
server {
    listen       80;
    server_name  blog.com;

    location / {
        root   /usr/share/nginx/html/blog;
        index  index.html index.htm;
    }
}

login.conf:

nginx 复制代码
server {
    listen       80;
    server_name  login.com;

    location / {
        root   /usr/share/nginx/html/login;
        index  index.html index.htm;
    }
}

第四步:重载配置

bash 复制代码
# 验证配置是否正确
docker exec nginx-learning nginx -t

# 重载配置(不中断服务)
docker exec nginx-learning nginx -s reload

验证效果

bash 复制代码
curl http://blog.com:8080/   # 返回 blog 站点的页面
curl http://login.com:8080/  # 返回 login 站点的页面

✅ 同一个 Nginx、同一个端口(80),通过不同的域名路由到不同的网站目录,这就是虚拟主机的核心能力。

四、server_name 匹配规则详解

server_name 支持多种匹配方式,灵活应对不同场景:

1. 精确匹配(完全匹配)

nginx 复制代码
server_name  example.com;
server_name  www.example.com;

必须与请求的域名完全一致才匹配。

2. 通配符匹配

* 只能出现在开头或结尾,不能放在中间:

nginx 复制代码
server_name  *.example.com;        # 匹配 www.example.com、api.example.com 等
server_name  mail.*;               # 匹配 mail.example.com、mail.test.com 等
server_name  *.example.*;           # ❌ 错误写法,通配符不能同时出现在开头和结尾

3. 正则匹配(~ 开头)

以 ~ 开头,后面跟正则表达式,提供最灵活的匹配能力:

nginx 复制代码
server_name  ~^www\d+\.example\.com$;  # 匹配 www1.example.com、www2.example.com 等
server_name  ~^(?<subdomain>.+)\.example\.net$;  # 支持捕获变量,可在配置中引用 $subdomain

注意事项:

  • 正则表达式必须以 ~ 开头
  • 正则中的 . 需要转义为 \\.
  • 正则匹配不区分大小写(如果需要区分大小写,使用 ~*)

4. 多域名并列

一个 Server 块可以指定多个域名,用空格隔开:

nginx 复制代码
server_name  example.com  www.example.com  blog.example.com;

5. 特殊值

写法 说明
server_name _; 下划线是常见的无效域名占位符 ,表示匹配任意未定义的域名,通常配合 default_server 使用
server_name ""; 匹配没有 Host 请求头的请求(如 HTTP/1.0 请求)

完整的多站点示例

nginx 复制代码
# 站点 1:主站
server {
    listen       80;
    server_name  example.com  www.example.com;

    location / {
        root   /var/www/main;
    }
}

# 站点 2:API 子域名
server {
    listen       80;
    server_name  api.example.com;

    location / {
        root   /var/www/api;
    }
}

# 站点 3:捕获所有未匹配的域名(兜底)
server {
    listen       80 default_server;
    server_name  _;

    return 444;  # 直接关闭连接,不给任何响应
}

五、server_name 匹配优先级

当多个 Server 块的 server_name 都能匹配同一个域名时,Nginx 按以下优先级只选一个:

优先级 匹配方式 示例
1(最高) 精确匹配 example.com
2 通配符开头 *.example.com
3 通配符结尾 www.*
4(最低) 正则匹配 ~^www\\.\\d+\\.com$

重要 :正则匹配实际上在通配符之后被检查,且 Nginx 会按配置文件中 正则出现的顺序 逐一尝试,匹配到第一个即停止。因此如果有多个正则都可能匹配,注意先后顺序。

六、default_server 的用法

default_server 用于指定某个 Server 块作为默认处理器,当没有其他规则匹配时使用:

nginx 复制代码
server {
    listen       80 default_server;
    server_name  _;

    location / {
        return 404;
    }
}

常见用途:

  • 拦截未绑定的域名 ------ 返回 404 或 444(直接关闭连接)
  • 统一重定向 ------ 将所有未匹配的请求重定向到主站
  • 统一 HTTPS 跳转 ------ 将所有 HTTP 请求跳转到 HTTPS

如果没有显式指定 default_server,Nginx 会使用该端口上的第一个 Server 块作为默认。

总结

通过本文,你已经掌握了 Nginx Server 块的核心配置:

知识点 要点
Server 块 虚拟主机的基本单元,每个块独立管理一个站点的路由规则
listen 指定监听的端口和协议
server_name 匹配请求头的 Host 字段,决定请求由哪个 Server 块处理
请求路由流程 listen 过滤端口 → server_name 匹配域名 → location 匹配路径
匹配规则 精确匹配 > 通配符开头 > 通配符结尾 > 正则匹配
default_server 未匹配时的兜底方案,用于拦截非法域名或统一重定向
多域名实战 修改 hosts → 编写多个 server 块 → 重载配置即可实现一机多站
相关推荐
zach1 小时前
Vue/React SPA 打包部署后,子路由刷新 401 未登录问题彻底解决
前端·nginx·next.js
yume_sibai4 小时前
02-Nginx进阶配置完全指南(性能优化 + 安全配置 + 缓存配置 + WebSocket代理)
nginx·安全·性能优化
阿狗童鞋4 小时前
Nginx反向代理与负载均衡实战指南
运维·nginx·负载均衡
Lsetea14 小时前
OpenSSL verify报error 20:CAfile、fullchain与本地信任链分层排查
nginx·https·ssl证书·openssl·证书链
qq_3945620020 小时前
【在Linux上升级nginx】
linux·服务器·nginx
冬、不眠的夜1 天前
分享一下 nginx 配置一个简单的 web 网站
nginx
孤狼GPT1 天前
ChatGPT、Codex排查实录:接口偶发502/504,应用日志却没有报错,到底该查哪一层?
nginx·codex·chatgptplus·chatgptpro·接口排查
2601_962381132 天前
历史视频朝代更替动效怎么做?把 AE 关键帧换成 AI 分镜动画的实战拆解
人工智能·nginx·音视频
数据杂坛2 天前
【Python程序开发系列】一文搞清楚Gunicorn以及和Nginx的区别
python·nginx·gunicorn