DocumentRoot不支持单VirtualHost内多根目录,必须用多个VirtualHost或Alias/ProxyPass实现子目录分离:1.为子域名配独立VirtualHost;2.用Alias映射路径或ProxyPass转发请求。

Apache 的 DocumentRoot 本身不支持“一个虚拟主机内共享多个根目录”,也不能为子目录单独指定不同 DocumentRoot。所谓“子目录访问分离”,实际是**用多个虚拟主机替代子目录路由**,或**用重写+应用层逻辑处理路径映射**——不是靠 DocumentRoot 拆分,而是靠请求匹配机制做分流。
为什么不能在同一个 VirtualHost 里设多个 DocumentRoot
DocumentRoot 指令的配置上下文仅限于“服务器配置”和“虚拟主机”层级,它不允许嵌套、重复或条件化定义。Apache 启动时只读取每个
<VirtualHost *:80>
DocumentRoot "/var/www/site-a"
DocumentRoot "/var/www/site-b" <!-- 无效,被忽略 -->
</VirtualHost>
会导致第二行完全失效。子目录(如 /blog、/api)的文件定位,始终基于该 VirtualHost 的唯一 DocumentRoot 展开,不会自动切换根路径。
可行的子目录分离方案
若你希望 example.com/blog 和 example.com/api 分别指向不同物理目录并独立运行(比如不同 PHP 版本、不同权限策略),有以下两种主流做法:
-
用多个基于名称的虚拟主机 + 自定义域名:为每个子站点分配专属子域名,如
blog.example.com和api.example.com,各自配独立 VirtualHost 和 DocumentRoot。这是最清晰、最易维护、最符合 Apache 设计逻辑的方式。 -
用 ProxyPass 或 Alias + 应用层路由:保持主站 DocumentRoot 不变,对特定路径做代理或别名映射。例如:
Alias /blog "/var/www/blog"<br><Directory "/var/www/blog"><br> Require all granted<br></Directory>
或用反向代理把/api/转发到本地另一个服务(如 Node.js 或不同 PHP-FPM 实例)。
常见误区与避坑点
以下操作看似“快捷”,但实际不可靠或违反设计原则:
- 在 .htaccess 中尝试用
DocumentRoot指令 —— 语法错误,Apache 直接拒绝加载; - 用
<Directory>块包裹子路径并改 DocumentRoot —— DocumentRoot 不允许出现在 Directory 上下文中; - 依赖 mod_vhost_alias 的泛虚拟主机自动映射子目录 —— 它只能按 Host 名动态选目录,不能按 URL 路径(如 /blog)动态切根;
- 把所有子站点代码放进同一 DocumentRoot 下再靠框架路由(如 Laravel 的 RouteServiceProvider)—— 这属于应用层隔离,DocumentRoot 仍是单一的,不解决静态资源、PHP 执行环境、权限控制等底层问题。
推荐配置结构示例
假设你要让 blog.example.com 和 api.example.com 各自独立运行:
<VirtualHost *:80>
ServerName blog.example.com
DocumentRoot "/var/www/blog"
<Directory "/var/www/blog">
Require all granted
AllowOverride All
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName api.example.com
DocumentRoot "/var/www/api"
<Directory "/var/www/api">
Require all granted
AllowOverride None
</Directory>
</VirtualHost>
确保 DNS 或 hosts 文件已将两个子域名解析到服务器 IP,且 Apache 已启用 mod_rewrite 和 mod_headers(如需 HTTPS 或 Header 控制)。


















