nginx try_files,proxy_pass和upstream

Ric*_*ape 8 php wordpress nginx

我正在为PHP应用程序构建一个dockerised测试'平台' - 特别是(暂时)用于WordPress.我正在使用PHPFarm在不同的端口上提供不同版本的PHP.在前面使用nginx,我已经有很多工作了.(https://github.com/richardtape/testit是主要的回购)

我现在面临的一个重大问题是让WordPress的"非常固定的"工作.在标准的nginx设置中,它只是一个类似的例子

location / {
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?$args;
}
Run Code Online (Sandbox Code Playgroud)

但是为了能够从主机获得不错的URL,并且为了拥有一个代码库,我使用了以下几行:

server {
    listen 80;
    index index.php index.html index.htm;
    server_name 52.spaces.dev;

    location / {

        proxy_pass http://phpfarm_52;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
    }
    root /var/www;
}

upstream phpfarm_52{
    server phpfarm:8052;
}
Run Code Online (Sandbox Code Playgroud)

现在,这是有效的.(对于PHP 5.3,5.4,5.5,5.6和7,还有5个类似的规则)主页加载来自主机的每个不同的server_names(如果你在每个上输出PHP版本,你可以看到你得到一个不同的PHP版本).

然而,第二个我切换到'内部'网址(或任何非根,即http://52.spaces.dev/about/),我得到一个404.我尝试过类似的东西

location / {
    try_files $uri $uri/ /index.php?$args
}

location ~ \.php$ {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}
Run Code Online (Sandbox Code Playgroud)

我得到一个重定向循环,取决于我尝试过的几种不同的方式,或者只是一系列301重定向,页面永远不会加载或错误,如

nginx_1      | 2016/04/08 20:31:29 [error] 5#5: *4 rewrite or internal redirection cycle while processing "/index.php", client: 192.168.99.1, server: 52.spaces.dev, request: "GET /favicon.ico HTTP/1.1", host: "52.spaces.dev", referrer: "http://52.spaces.dev/"
Run Code Online (Sandbox Code Playgroud)

我被卡住了.我也是nginx配置的新手(这可能是显而易见的)所以我可能会做一些完全错误和/或愚蠢的事情.有什么建议?

tal*_*dor 9

您在问题中遇到重定向循环的问题是,基本上每个请求,即使对于静态文件,也会尝试通过index.php?$ args块进行路由.

我在这里看到了两种可能的解 首先,如果您愿意使用单个nginx实例实现nginx设置,请查看此主题:具有多个命名位置的NGINX try_files和此博客文章http://linuxplayer.org/2013/06/nginx-try-files-上多命名位置或服务器

需要发生的是,您需要首先测试资源是否存在于上游(即,不返回404).如果是,那么你按原样服务.如果没有,那么你将调用重写块,它试图将它作为index.php的参数.所以你最终得到这样的东西(对不起,我真的没有机会测试这个,但希望它能给出一个想法):

location / {
    try_files $uri $uri/ @phpproxy;
}

location @phpproxy {
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_intercept_errors on;
    recursive_error_pages on;
    error_page 404 = @rewrite_proxy;
}

location @rewrite_proxy {
    rewrite ^/(.*)$ /index.php?$1 break;
    proxy_pass http://phpfarm_52;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $remote_addr;
}
Run Code Online (Sandbox Code Playgroud)

第二种解决方案(我个人更喜欢)是使用自己的nginx在每个上游.然后,面向所有其他人的顶级nginx将具有更简洁的proxy_pass(+可能是一些静态内容)的更清晰的结构,就是这样.它还将减少往返请求,因为您不需要解决来自上游的404.