使用 Nginx/Fastcgi 在子 URL 下部署 django

Posted

技术标签:

【中文标题】使用 Nginx/Fastcgi 在子 URL 下部署 django【英文标题】:Deploying django under a sub-URL with Nginx/Fastcgi 【发布时间】:2011-03-24 23:13:16 【问题描述】:

我一辈子都不知道如何使用 nginx/fastcgi 在非 root 位置下部署 django 站点,例如http://localhost:8080/myproject/ 而不是 http://localhost:8080/;我看到的所有示例都假设 Apache 或安装在站点的根目录。这是我nginx.conf的相关部分:

server 
    listen 8080;
    server_name localhost;

    location /myproject/ 
        # host and port to fastcgi server
        fastcgi_pass 127.0.0.1:3030;

        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        #fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  PATH_INFO          $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
    

还有一个最小的urls.py

from django.http import HttpResponse
from django.conf.urls.defaults import patterns

urlpatterns = patterns('',
    (r'^hello$', lambda request: HttpResponse('Hello world!')),

)

尝试访问 http://localhost:8080/myproject/hello 时会出现 404。我尝试了以下所有组合均未成功:

评论/取消评论fastcgi_param PATH_INFO $fastcgi_script_name; 评论/取消评论fastcgi_param SCRIPT_NAME $fastcgi_script_name; 在 settings.py 中设置FORCE_SCRIPT_NAME = '/myproject/'

【问题讨论】:

【参考方案1】:

我自己刚刚解决了同样的问题 - 事实证明,您在 ServerFault 上提供的指向 Django change doc 的链接是解决问题的关键。

Django > 1.0 使用 SCRIPT_NAMEPATH_INFO 来路由 URL,正如文档解释的那样。所以我拿着它跑了。对于您希望植根于 mydomain.com/myproject/ 的名为“myproject”的项目,试试这个。

location ~ /myproject/(.*)$ 
    fastcgi_pass 127.0.0.1:8080;
    fastcgi_param  PATH_INFO /$1;
    SCRIPT_NAME /myproject;

我在另一个站点范围的配置文件中拥有的其余 fastcgi 参数。所以你的例子看起来像

server 
    listen 8080;
    server_name localhost;

    location /myproject/ 
        # host and port to fastcgi server
        fastcgi_pass 127.0.0.1:3030;

        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;

        fastcgi_param  SCRIPT_NAME        /myproject;
        fastcgi_param  PATH_INFO          /$1;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;

        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;
    

使用相同的 urls.py。到目前为止,我遇到的唯一问题是保持 DRY 的小问题,例如 settings.py 需要绝对 URL,而 Django 不认为在 URL 上添加 SCRIPT_NAME(想想 settings.LOGIN_URLsettings.MEDIA_URL)。

这可能很明显,但也要确保您有另一个指向静态和管理媒体的位置。

【讨论】:

@gsakkis,这对你有帮助吗? 它帮助了我...我使用这种方法在 nginx.conf 中的同一台服务器上托管了两个 webapp。但我的问题是两者都需要不同的静态和媒体网址......在这里做什么??【参考方案2】:

试试这个配置

    location  /myproject 
    fastcgi_split_path_info ^(/myproject)(.*)$;
    fastcgi_pass 127.0.0.1:8080;
    include fastcgi_params;

其中,fastcgi_params 文件包含

    fastcgi_param  QUERY_STRING       $query_string;
    fastcgi_param  REQUEST_METHOD     $request_method;
    fastcgi_param  CONTENT_TYPE       $content_type;
    fastcgi_param  CONTENT_LENGTH     $content_length;

    fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
    fastcgi_param  REQUEST_URI        $request_uri;
    fastcgi_param  DOCUMENT_URI       $document_uri;
    fastcgi_param  DOCUMENT_ROOT      $document_root;
    fastcgi_param  SERVER_PROTOCOL    $server_protocol;

    fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
    fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

    fastcgi_param  REMOTE_ADDR        $remote_addr;
    fastcgi_param  REMOTE_PORT        $remote_port;
    fastcgi_param  SERVER_ADDR        $server_addr;
    fastcgi_param  SERVER_PORT        $server_port;
    fastcgi_param  SERVER_NAME        $server_name;

    fastcgi_param  PATH_INFO          $fastcgi_path_info;

    # php only, required if PHP was built with --enable-force-cgi-redirect
    fastcgi_param  REDIRECT_STATUS    200;

它对我有用。

请参阅有关 fastcgi_split_path_info 的文档

【讨论】:

【参考方案3】:

因为我自己遇到了子 URL 问题,所以偶然发现了您的问题。我的服务器使用 Apache 作为其主服务器,所以我的配置有所不同,但它可以工作。也许这会对某人有所帮助:

Apache 在端口 80(主 Web 服务器)上 localhost:3033 上的 nginx(随机端口) 在 localhost:3034 上的 manage.py fastcgi

那么 Apache 配置看起来像这样(nginx 的代理):

<Location /blogsite/>
    Order deny,allow
    Allow from all

    ProxyPass http://127.0.0.1:3033/
    ProxyPassReverse http://127.0.0.1:3033/
</Location>

而nginx站点配置为:

server 
    listen 127.0.0.1:3033;
    server_name localhost;

    location / 
        fastcgi_pass 127.0.0.1:3034;
        fastcgi_param PATH_INFO $fastcgi_script_name;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;
        fastcgi_pass_header Authorization;
        fastcgi_intercept_errors off;
    

    access_log  /var/log/nginx/blogsite.access_log;
    error_log   /var/log/nginx/blogsite.error_log;

我认为您遇到的问题是由于某种方式的 nginx 配置,而不是 Django 部署的问题。您可能想试试我发布的解决方案是否适合您。

【讨论】:

以上是关于使用 Nginx/Fastcgi 在子 URL 下部署 django的主要内容,如果未能解决你的问题,请参考以下文章

nginx_3_反向代理负载均衡缓存URL重写

nginx+fastcgi php 使用file_get_contentscurlfopen读取localhost本站点.php异常的情况

nginx FastCGI错误Primary script unknown解决办法

Nginx + fastcgi 截断问题

nginx fastcgi 超时问题

nginx fastcgi 超时问题