使用gunicorn和nginx部署Django

时间:2012-10-22 03:00:23

标签: django deployment nginx setup-deployment gunicorn

这是一个广泛的问题,但我想得到一个规范的答案。我一直在尝试使用 gunicorn nginx Django 中部署网站。在阅读了大量的教程后,我已经取得了成功,但我无法确定我所遵循的步骤是否足以运行一个没有问题的站点,或者可能有更好的方法来实现它。这种不确定性很烦人。

这就是为什么我正在为新手寻找一个非常详细且解释清楚的答案。我不想过多地解释我所知道的和我不知道的事情,因为这可能会使答案有所偏差,而其他人可能会从你的答案中获益较少。但是,我想提到的一些事情是:

  • 您认为哪种“设置”效果最佳?我使用了 virtualenv 并将我的 Django 项目移到了这个环境中,但是我看到了另一个设置,其中有一个虚拟环境文件夹和其他项目文件夹。

    < / LI>
  • 如何以允许多个网站托管在单个服务器中的方式设置内容?

  • 为什么有人建议使用gunicorn_django -b 0.0.0.0:8000而其他人建议使用gunicorn_django -b 127.0.0.1:8000?我在Amazon EC2实例中对后者进行了测试,但是当前者没有问题时它没有工作。

  • nginx的配置文件背后的逻辑是什么?有很多教程使用截然不同的配置文件,我很困惑哪一个更好。例如,有些人使用alias /path/to/static/folder和其他root /path/to/static/folder。也许您可以共享首选配置文件。

  • 为什么我们在site-available中的sites-enabled/etc/nginx之间创建符号链接?

  • 一些最佳实践一如既往地欢迎: - )

由于

4 个答案:

答案 0 :(得分:104)

  

什么&#34;设置&#34;你见过最好的工作吗?我使用了virtualenv并感动了我的   django项目在这个环境里面,但是我见过另一个   设置有虚拟环境的文件夹和其他的文件夹   项目

virtualenv是一种隔离Python环境的方法;因此,它在部署中没有很大的作用 - 但是在开发测试期间,如果没有强烈推荐。

您从virtualenv获得的价值是它允许您确保为应用程序安装了正确版本的库。因此,坚持虚拟环境本身并不重要。请确保您不将其作为源代码版本控制系统的一部分包含在内。

文件系统布局并不重要。您将看到许多文章赞美目录布局的优点,甚至可以克隆的骨架项目作为起点。我觉得这更像是个人偏好而不是硬性要求。当然很高兴;但除非您知道原因,否则它不会为您的部署过程添加任何价值 - 所以不要这样做,因为除非对您的方案有意义,否则某些博客会推荐它。例如 - 如果您没有属于部署工作流程的私有PyPi服务器,则无需创建setup.py文件。

  

如何以允许托管多个网站的方式设置内容   在一台服务器上?

您需要做两件事来进行多个网站设置:

  1. 如果您有SSL,则在端口80和/或端口443上侦听公共IP的服务器。
  2. 一堆&#34;流程&#34;正在运行实际的django源代码。
  3. 人们使用nginx作为#1,因为它是一个非常快速的代理,它不会带来像Apache这样的综合服务器的开销。如果您对它感到满意,可以自由使用Apache。对于多个站点,没有要求使用nginx&#34 ;;你只需要一个正在侦听该端口的服务,知道如何将(代理)重定向到运行实际django代码的进程。

    对于#2,有几种方法可以启动这些过程。 gevent / uwsgi是最受欢迎的。这里要记住的唯一事情是不要在生产中使用runserver

    这些是绝对最低要求。通常人们会添加某种流程管理器来控制所有&#34; django服务器&#34; (#2)跑步。在这里,您会看到提到的upstartsupervisor。我更喜欢主管,因为它不需要接管整个系统(不像暴发户)。但是,再次 - 这不是硬性要求。你可以完美地运行一堆screen个会话并解除它们。缺点是,如果服务器重新启动,则必须重新启动屏幕会话。

    我个人建议:

    1. Nginx for#1
    2. 在uwsgi和gunicorn之间选择 - 我使用uwsgi。
    3. supervisor用于管理后端进程。
    4. 您托管的每个应用程序的个人系统帐户(用户)。
    5. 我推荐#4的原因是隔离权限;再次,不是要求。

        

      为什么有些人建议使用gunicorn_django -b 0.0.0.0:8000和   其他人建议gunicorn_django -b 127.0.0.1:8000?我测试了后者   在Amazon EC2实例中,但在前者工作时它没有工作   没问题。

      0.0.0.0表示&#34;所有IP地址&#34; - 它的元地址(即占位符地址)。 127.0.0.1是一个始终指向本地计算机的保留地址。这就是为什么它被称为&#34; localhost&#34;。它只能在同一系统上运行的进程访问。

      通常,您有前端服务器(上面列表中的#1)监听公共IP地址。您应明确将服务器绑定到一个 IP地址

      但是,如果由于某种原因您使用的是DHCP或者您不知道IP地址是什么(例如,它是新配置的系统),您可以告诉nginx / apache /任何其他进程绑定到0.0.0.0这应该是临时止差措施

      对于生产服务器,您将拥有静态IP。如果您有动态IP(DHCP),则可以离开0.0.0.0。但是,您的生产机器很少有DHCP。

      将gunicorn / uwsgi绑定到此地址不推荐在制作中。如果您将后端进程(gunicorn / uwsgi)绑定到0.0.0.0,它可能会直接访问&#34;绕过您的前端代理(nginx / apache / etc);有人可以直接请求http://your.public.ip.address:9000/并直接访问您的应用程序 ,特别是如果您的前端服务器(nginx)和后端进程(django / uwsgi / gevent)在同一台计算机上运行

      如果你不想让运行前端代理服务器的麻烦,你可以自由地这样做。

        

      nginx配置文件背后的逻辑是什么?有这么多   教程使用了与我完全不同的配置文件   困惑哪一个更好。例如,有些人使用&#34;别名   /路径/到/静态/文件夹&#34;和其他人&#34; root / path / to / static / folder&#34;。   也许你可以分享你喜欢的配置文件。

      关于nginx,你应该知道的第一件事是不是像Apache或IIS那样的网络服务器。这是一个代理人。因此,您会看到不同的字词,例如上游&#39; /&#39;下游&#39;和多个服务器&#34;被定义。花点时间先阅读nginx手册。

      设置nginx的方法有很多种;但是这里是关于aliasroot的问题的一个答案。 root是一个显式指令,用于绑定nginx的文档根目录(&#34;主目录&#34;)。这是当您提交没有http://www.example.com/

      之类的路径的请求时它将查看的目录

      alias表示&#34;将名称映射到目录&#34;。别名目录可能不是文档根目录的子目录。

        

      为什么我们在网站可用和网站启用之间创建一个符号链接   的/ etc / nginx的?

      这是debian(和像ubuntu一样的类似debian的系统)的独特之处。 sites-available列出系统上所有虚拟主机/站点的配置文件。从sites-enabledsites-available&#34;的符号链接会激活&#34;该站点或虚拟主机。这是一种分离配置文件并轻松启用/禁用主机的方法。

答案 1 :(得分:11)

我不是部署专家,但会分享我使用gevent部署Django的一些做法(尽管应该类似于gunicorn)。

virtualenv非常棒,因为我不会参与其中。然而,我发现virtualenv-wrapperdocs)非常有用,尤其是当您处理许多项目时,因为它允许在不同的virtualenv之间轻松切换。这并不适用于部署环境,但是当我需要使用SSH在服务器上进行故障排除时,我发现这非常有用。使用它的另一个好处是它管理virtualenv目录,因此减少了手动工作。 Virtualenvs应该是一次性的,以便在您遇到版本问题或任何其他安装问题时,您可以转储env并创建一个新的。因此,最好不要在virtualenv中包含任何项目代码。它应该分开。

至于设置多个网站,virtualenv几乎就是答案。你应该为每个项目都有一个单独的virutalenv。只有这一点才能解决许多问题。然后在部署时,不同的Python进程将运行不同的站点,这可以避免部署之间出现任何可能的冲突。我特别发现在同一服务器上管理多个站点非常有用的一个工具是supervisordocs)。它为启动,停止和重新启动不同的Django实例提供了一个简单的界面。它还能够在失败或计算机启动时自动重启进程。因此,举例来说,如果引发了一些异常而没有任何异常,整个网站都会崩溃。主管将捕获它并将自动重启Django实例。以下是示例管理程序(单个进程)配置:

[program:foo]
command=/path/toviertualenv/bin/python deploy.py
directory=/path/where/deploy.py/is/located/
autostart=true
autorestart=true
redirect_stderr=True
user=www

对于Nginx,我知道一开始可能会让人不知所措。我发现Nginx book非常有用。它解释了所有主要的nginx指令。

在我的nginx安装中,我发现最佳做法是只设置nginx.conf文件中的核心配置,然后我有一个单独的文件夹sites,我保留每个文件夹的nginx配置我主持的网站。然后我只在核心配置文件中包含该文件夹中的所有文件。我使用指令include sites/+*.conf;。这样,它只包含+文件夹中以sites符号开头的文件。这样只需通过文件名我可以控制哪些配置文件被加载。因此,如果我想禁用某个站点,我只需要重命名配置文件并重新启动nginx。在你的问题中,不确定你在“/ etc / nginx中的站点可用和站点启用之间的符号链接”中的含义是什么,因为它们是Apache命名的文件夹,但它们完成了与include指令类似的任务。

对于rootalias指令,它们几乎相同,除非计算其根。在alias中,无论在location中丢弃了什么,而在根中没有。您拥有以下nginx配置的图像:

location /static {
    alias /some/path/;
}
location /static2 {
    root /some/other/path/;
}

如果用户访问这些网址,则nginx会尝试在系统的以下位置查找文件:

/static/hello/world.pdf => /some/path/hello/world.pdf
/static2/hello/world.pdf => /some/other/path/static2/hello/world.pdf

这是nginx网站的简单配置:

server {
    server_name .foodomain.com;
    listen 80;

    access_log logs/foodomain.log;

    gzip                on;
    gzip_http_version   1.0;
    gzip_comp_level     2;
    gzip_proxied        any;
    gzip_min_length     1100;
    gzip_buffers        16 8k;
    gzip_types          text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    # Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    # Set a vary header so downstream proxies don't send cached gzipped content to IE6
    gzip_vary on;

    location / {
        proxy_read_timeout      30s;
        proxy_pass              http://localhost:8000;
        proxy_set_header        Host                 $host;
        proxy_set_header        User-Agent           $http_user_agent;
        proxy_set_header        X-Real-IP            $remote_addr;
    }

    location /media {
        alias   /path/to/media/;
        expires 1y;
    }

    location /static {
        autoindex on;
        expires   1y;
        alias     /path/to/static/;
    }

     location /favicon.ico {
        alias /path/to/favicon.ico;
    }
}

希望这对你有所帮助。

答案 2 :(得分:2)

嗯,就你在问题中提出的最佳做法而言,我无法帮助分享一个能为我创造奇迹的工具!我自己曾经在几个网站的gunicorn,nginx,supervisorD的几个配置文件中感到困惑!但我渴望以某种方式自动化整个过程,以便我可以对我的应用程序/站点进行更改并立即进行部署。它的名字是django-fagungis。您可以使用Django Deployment automation here找到我的体验详情。我刚刚配置了一个fabfile.py ONCE(django-fagungis使用fabric来自动完成整个过程,并在你的远程服务器上创建一个非常方便的virtualenv来管理托管在单个服务器上的几个站点的依赖关系。它使用nginx,gunicorn和supervisorD来处理Django项目/站点部署),django-fagungis从bitbucket(我用于颠覆)克隆我的最新项目并将其部署在我的远程服务器上,我只需要在shell上输入三个命令我的本地机器,它!对我来说,这已经证明是Django部署的最佳和最轻松的练习。

答案 3 :(得分:2)

检查这是否为Django项目所需的最小gunicorn和nginx配置。 http://agiliq.com/blog/2013/08/minimal-nginx-and-gunicorn-configuration-for-djang/