
本文详解如何通过 Nginx 容器反向代理同一 Docker 网络内的两个独立 Laravel PHP 应用(如前台 app 和后台 admin),解决路径冲突、try_files 误匹配及 FastCGI 路由失效问题。
本文详解如何通过 nginx 容器反向代理同一 docker 网络内的两个独立 laravel php 应用(如前台 `app` 和后台 `admin`),解决路径冲突、`try_files` 误匹配及 fastcgi 路由失效问题。
在 Docker 多容器 Laravel 架构中,常见需求是:
- 主应用(如
http://localhost:9000/)托管前台网站; - 后台应用(如
http://localhost:9000/admin)托管管理后台,物理上为另一套 Laravel 代码 + 独立 PHP-FPM 进程。
此时,Nginx 不再是静态文件服务器,而是基于路径的反向代理网关——它需将 /admin/* 请求精准转发至 admin 容器的 PHP-FPM,而非错误地交由 app 处理。原配置失败的根本原因有三点:
-
location /admin与location /顺序不当:Nginx 按字典序匹配location,但更关键的是try_files $uri $uri/ /index.php?$query_string在location /中会提前捕获/admin请求,并重写为/index.php?admin,最终发往app:9000; -
缺少路径重写逻辑:
admin容器的入口应为/var/www/public/index.php,但原始请求 URI(如/admin/login)需被转换为index.php可识别的PATH_INFO; -
FastCGI 上下文隔离缺失:
/admin下的 PHP 请求必须使用admin:9000的 upstream,且SCRIPT_FILENAME、PATH_INFO需适配其文档根目录(/var/www/public),而非共享app的路径。
✅ 正确做法是采用 命名 location + rewrite + 精确 FastCGI 配置 组合:
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
# 主应用根目录(仅作参考,实际由 location / 内部指定)
root /var/www/public;
# ① 优先匹配 /admin 前缀,交由命名 location @admin_proxy 处理
location /admin {
try_files $uri @admin_proxy;
}
# ② 命名 location:重写路径并转发至 admin 容器
location @admin_proxy {
# 将 /admin/login → /index.php?/admin/login(保留原始路径作为 PATH_INFO)
rewrite ^/admin/(.*)$ /index.php?/$1 break;
# 或更通用写法(若需支持 /admin/api/xxx):
# rewrite ^/admin(/.*)?$ /index.php?/$1 break;
# 关键:设置 admin 容器的文档根(注意:此处 root 必须与 admin 容器内 public 路径一致)
root /var/www;
# FastCGI 标准配置(指向 admin 容器)
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass admin:9000; # ← 指向 admin 容器
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/public/index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param REQUEST_URI $request_uri; # 确保 Laravel 路由器获取原始 URI
}
# ③ 主应用:/ 及其子路径(排除 /admin 已被拦截)
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
# 主应用的 PHP 处理块(嵌套在 location / 内,避免污染全局)
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000; # ← 指向 app 容器
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
}
? 关键注意事项:
-
Docker 网络连通性:确保
nginx容器能通过服务名admin和app解析并访问对应容器(docker-compose.yml中已声明app-network,无需额外配置); -
PHP-FPM 监听地址:
admin和app容器的 PHP-FPM 必须监听0.0.0.0:9000(而非127.0.0.1:9000),否则 Nginx 无法跨容器连接;检查其www.conf中listen = 9000或listen = 0.0.0.0:9000; -
文档根一致性:
admin容器内代码结构应为/var/www/public/...,root /var/www+SCRIPT_FILENAME $document_root/public/index.php确保路径正确; -
Laravel 配置适配:
admin应用的.env中需设置APP_URL=http://localhost:9000/admin,并确保APP_PATH(如有自定义)兼容子路径路由; -
性能优化建议:生产环境应启用
fastcgi_cache并分离静态资源(如/admin/assets/直接由 Nginx 服务),避免 PHP 处理。
? 进阶替代方案(更清晰可维护):
若项目规模扩大,推荐改用 多 server 块 + 子域名(如 app.example.test / admin.example.test),或使用 upstream 块显式定义后端集群,再配合 proxy_pass(适用于非 PHP 应用)或 fastcgi_pass。但对于路径前缀场景,上述命名 location 方案已在实践中验证稳定可靠。











