【Nginx 从入门到实战 07】root 与 alias:资源路径到底怎样对应?

上一篇,我们弄清了请求会命中哪段 location。这一篇继续往下走:命中之后,Nginx 到哪里找文件?

继续使用 Windows + CMD。准备一张图片,用两个地址访问同一个文件,再故意配错一次,看看 404 是怎么产生的。

一、先记住最关键的区别

对于本篇这种简单的前缀 location、没有 rewrite 的静态文件请求:

指令 路径处理方式
root 在指定目录后拼接完整 URI 路径
alias 用指定目录替换命中的 location 前缀,再接剩余路径

注意,这里的 URI 路径不包含查询参数。

例如,磁盘中只有一个图片文件:

text 复制代码
html/lesson07/images/banner.svg

我们希望:

  • /images/banner.svg 使用 root 访问它。
  • /pictures/banner.svg 使用 alias 访问它。

两个 URL 可以指向同一个文件,URL 中的目录名称不一定要和磁盘目录名称一样。1

二、准备实验文件

1. 创建目录

在 CMD 中进入 Nginx 安装目录:

cmd 复制代码
cd /d D:\devtools\nginx
mkdir html\lesson07\images

安装路径不同,换成自己的路径。目录已存在时不需要重复创建。

本篇只需要两个文件:

文件 用途
html/lesson07/index.html 对照页面
html/lesson07/images/banner.svg 两个地址共同访问的图片

你也可以使用配套示例包:把 demo/html/lesson07 整个文件夹复制到 Nginx 的 html 目录下,避免多套一层目录。

2. 准备图片

如果做过第五篇,可以复制之前的图片:

cmd 复制代码
copy html\lesson05\images\banner.svg html\lesson07\images\banner.svg

没有这个文件,也可以新建:

cmd 复制代码
notepad html\lesson07\images\banner.svg

写入下面的内容,保存为 UTF-8,确认文件名不是 banner.svg.txt:

svg 复制代码
<svg xmlns="http://www.w3.org/2000/svg" width="720" height="240" viewBox="0 0 720 240">
    <rect width="720" height="240" rx="20" fill="#009b62"/>
    <circle cx="655" cy="40" r="110" fill="#20be87"/>
    <text x="40" y="112" font-family="Arial,sans-serif" font-size="48" font-weight="bold" fill="white">Hello, Nginx!</text>
    <text x="42" y="164" font-family="Arial,sans-serif" font-size="22" fill="white">HTML + CSS + IMAGE</text>
</svg>

SVG 本身就是图片文件,不需要再转换成 PNG。

3. 创建对照页面

cmd 复制代码
notepad html\lesson07\index.html

写入:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>root 与 alias 对照实验</title>
    <style>
        body { max-width: 760px; margin: 40px auto; padding: 0 20px;
               font-family: system-ui, sans-serif; color: #153c30; }
        img { width: 100%; display: block; margin: 16px 0 32px; }
    </style>
</head>
<body>
    <h1>同一个文件,两种资源路径</h1>
    <h2>root:/images/banner.svg</h2>
    <img src="/images/banner.svg" alt="使用 root 访问的图片">
    <h2>alias:/pictures/banner.svg</h2>
    <img src="/pictures/banner.svg" alt="使用 alias 访问的图片">
</body>
</html>

这里故意用了两个不同的图片地址。接下来让它们映射到同一个文件。

三、新增实验站点

1. 备份并打开配置

仍在安装目录的 CMD 中执行:

cmd 复制代码
copy conf\nginx.conf conf\nginx.conf.lesson07.bak
notepad conf\nginx.conf

备份已存在时,先确认是否要保留,再决定是否覆盖。

2. 在 http 块内新增 server

将下面的配置放进现有 http { ... } 内,与其他 server 平级:

nginx 复制代码
server {
    listen 127.0.0.1:8093;
    server_name localhost;

    root html/lesson07;
    index index.html;
    charset utf-8;
    error_log logs/lesson07_error.log;

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

    location /images/ {
        root html/lesson07;
    }

    location /pictures/ {
        alias html/lesson07/images/;
    }
}

这只是新增站点,不是整份配置。不要删掉已有的 events、http 或其他站点。

确认现有 http 内仍保留标准 MIME 类型映射,已有时不要重复添加:

nginx 复制代码
include mime.types;
default_type application/octet-stream;

上一篇的 types { } 是诊断文本实验专用配置,本篇不要复制进来。

这里的相对文件路径以 Nginx 的运行前缀为基础。本系列一直从安装目录启动,所以 html/lesson07 对应安装目录下的站点文件夹。2

3. 检查并加载

cmd 复制代码
nginx -t

检查通过后,已经运行的实例执行:

cmd 复制代码
nginx -s reload

如果尚未启动:

cmd 复制代码
start nginx

端口 8093 仅供本机练习。若端口被占用,替换配置中的端口,并同步修改访问地址。

四、分别看 root 和 alias 怎么找文件

1. root:完整路径接在后面

配置:

nginx 复制代码
location /images/ {
    root html/lesson07;
}

访问:

text 复制代码
http://127.0.0.1:8093/images/banner.svg

文件路径的形成过程:

text 复制代码
root 指定目录:html/lesson07
请求 URI 路径:/images/banner.svg
最终文件路径:html/lesson07/images/banner.svg

root 不会因为写在 /images/ 的 location 中,就自动去掉请求中的 /images/。1

虽然这里显式写了一次 root 方便对照,但它和 server 级别的值相同。删掉这个 location 中的 root 后,也可以继承上层配置。

2. alias:替换前缀,再接剩余部分

配置:

nginx 复制代码
location /pictures/ {
    alias html/lesson07/images/;
}

访问:

text 复制代码
http://127.0.0.1:8093/pictures/banner.svg

可以分成两部分理解:

text 复制代码
匹配的 location 前缀:/pictures/
剩余路径:banner.svg
alias 指定目录:html/lesson07/images/
最终文件路径:html/lesson07/images/banner.svg

这里 /pictures/ 被 alias 指定的目录替换,所以不会再多出一层 pictures。1

本例的目录映射把 location 和 alias 目录都写成以 / 结尾,清楚地表达目录边界。

3. 打开对照页面

text 复制代码
http://127.0.0.1:8093/

预期看到两张相同的绿色横幅。

还要分别打开上面的两个图片地址,确认它们都能独立显示。可以在浏览器 Network 面板查看请求,正常响应的类型应为 image/svg+xml。

只创建了一份图片,页面展示两次;并没有在磁盘上再复制一个 pictures 文件夹。

五、故意配错一次:为什么变成 404?

将原来 /pictures/ 中的:

nginx 复制代码
alias html/lesson07/images/;

临时改成:

nginx 复制代码
root html/lesson07/images;

注意,是替换这一行,不要同时保留两种写法。

执行配置检查和 reload 后,再访问:

text 复制代码
http://127.0.0.1:8093/pictures/banner.svg

因为此时使用的是 root,会把完整 URI 接到目录后面:

text 复制代码
html/lesson07/images/pictures/banner.svg

我们并没有创建这个文件,所以在本篇原始文件布局下,应返回 404。

配置方式 查找路径 本例结果
alias html/lesson07/images/; html/lesson07/images/banner.svg 找到图片
root html/lesson07/images; html/lesson07/images/pictures/banner.svg 找不到文件

配置语法正确,不代表文件路径正确。 nginx -t 不会逐一验证未来每个请求对应的资源是否存在。

实验结束后,把这一行恢复为 alias html/lesson07/images/;,再次检查并 reload。

六、访问失败时,先看这三件事

1. 到底命中了哪段 location?

先按上一篇的规则检查。

即使 alias 写对了,如果请求最终被其他正则 location 处理,也可能根本没有使用这段路径映射。

本篇没有配置正则,因此不用额外加 ^~。如果后续增加正则,再根据实际分工决定是否需要它。

2. Nginx 实际尝试打开什么文件?

本篇单独设置了错误日志:

nginx 复制代码
error_log logs/lesson07_error.log;

产生错误后,在 CMD 查看:

cmd 复制代码
type logs\lesson07_error.log

重点找包含文件打开失败的信息,核对其中的实际路径。

在刚才的错误实验中,路径会多出 pictures 这一层。看到这层目录,通常就能发现把 alias 的思路误写成了 root。

错误日志可能包含先前请求的记录,要结合最新时间和请求地址判断。如果没有文件打开失败记录,还要检查请求是否到达本实例、日志级别和配置是否生效。

3. 文件名、目录和权限是否正确?

在 CMD 中确认图片确实存在:

cmd 复制代码
dir html\lesson07\images\banner.svg

同时检查:

  • 是否多复制了一层文件夹。
  • 扩展名是否被保存成 .svg.txt。
  • 文件名大小写是否一致,尤其是以后迁移到 Linux 时。
  • Nginx 运行账户是否有读取文件和访问父目录的权限。

不要看到 404 就反复 reload;修改文件布局和修改配置,是两种不同的排查方向。

七、几个经常被误解的问题

1. alias 后面一定要写绝对路径吗?

不一定,本篇使用的就是相对路径。为了便于定位,实际部署也可以使用明确的绝对路径。

例如 Windows 配置中可以写:

nginx 复制代码
alias D:/devtools/nginx/html/lesson07/images/;

Nginx 配置中的 Windows 路径使用正斜杠 /。2 这和 CMD 命令里常见的反斜杠 \ 不同。

绝对路径中的盘符和目录只是示例,必须根据实际安装位置修改。

2. alias 的结尾斜杠能随便省略吗?

对于本篇这种"带结尾斜杠的前缀映射到目录"的写法,建议保持:

nginx 复制代码
location /pictures/ {
    alias html/lesson07/images/;
}

不要随意删掉 alias 目录末尾的 /。目录与剩余文件名之间需要正确的分隔。

这不等于"所有 alias 都必须以斜杠结尾":精确匹配到单个文件等场景可以指向文件。本篇先把目录映射写清楚。

3. 访问 /pictures/ 返回 403,是不是 alias 失效了?

不一定。访问目录时,如果没有可用的默认首页,同时没有开启目录列表,就可能返回 403。

本篇的 images 目录没有首页,因此验证映射时直接访问:

text 复制代码
/pictures/banner.svg

不要为了消除目录访问的 403,就随手打开目录列表。你要验证的是文件能否访问,不是展示文件夹中的所有文件。

/pictures 和 /pictures/ 也不是同一个路径。本篇未额外处理不带结尾斜杠的 /pictures。

4. alias 里也能直接照搬 SPA 的 try_files 吗?

不要机械照搬。

本篇 alias location 直接提供静态文件,没有额外添加 try_files;文件不存在时,静态文件处理会返回相应错误。

如果再结合正则、rewrite、try_files 或首页回退,需要重新分析 URI、映射路径及内部重定向。先用简单前缀映射确认文件可访问,再逐项增加行为。

5. root 和 alias,该优先用哪个?

看 URL 和磁盘目录是否自然对应:

  • 站点结构与 URL 一致时,用 root 通常更直接。
  • 想把 /pictures/ 映射到另一个名字或位置的目录时,用 alias 更清晰。

二者都用于路径映射,不是权限验证。部署真实附件目录时,只映射计划公开的资源,不要把整个项目或磁盘根目录作为公开资源目录。

八、本篇回顾

本篇用两个 URL 访问了同一个文件,并通过修改一行配置复现了 404。

记住三个动作:

  1. 先判断 location:请求最终使用哪段配置。
  2. 再计算文件路径:root 接完整 URI,简单前缀 alias 替换匹配前缀。
  3. 最后核对文件:对照错误日志检查目录、文件名与读取权限。

下一篇:《【Nginx 从入门到实战 08】反向代理入门:让 Nginx 转发后端接口》。

我们会搭一个最小后端服务,实际观察请求经过 Nginx 转发后的路径与响应。

参考资料

  1. Nginx HTTP 核心模块:root、alias、location
  2. Nginx Windows 使用说明:相对路径与路径分隔符
相关推荐
SL_staff2 小时前
10人团队如何用轻量私有化文档平台实现知识复用提效?技术视角拆解B/S架构下的协作闭环
java·开源·全栈
前端双越老师3 小时前
程序员 1v1 访谈系列第十期:纯前端坚持不了多久了
前端·ai编程·全栈
acd120095 小时前
Nginx 反向代理的缓冲区坑:后端响应大时接口偶发 502
java·运维·nginx
Thanks_ks5 小时前
常见 HTTP 状态码的坑:301/302、401/403、500/502 之间差的那一个词
计算机网络·nginx·http·面试·状态码·后端开发·浏览器缓存
濮水大叔7 小时前
React/Next.js 生态里,有没有 CabloyJS 这样的全栈框架?
react.js·全栈·next.js
SL_staff9 小时前
3分钟完成业务规则调整:告别代码修改,实现拖拽式逻辑配置
java·低代码·全栈
濮水大叔9 小时前
AI Vibe Coding 实战(续):SMS 套件产品决策与开发方案
ai编程·全栈·vibecoding
Lsetea1 天前
Certbot webroot申请SSL证书总是404:Nginx挑战目录与路径映射检查
运维·nginx·https·ssl证书·certbot
莫晓燚1 天前
双机部署若依 (RuoYi‑Vue) 传统环境部署---实战
linux·运维·数据库·redis·mysql·nginx·ruoyi