A Django setup using Nginx and Gunicorn

本文提供了一个使用Nginx作为反向代理和Gunicorn作为Django服务的部署教程,介绍了如何在Linux(Ubuntu)系统上配置Django项目。

http://goodcode.io/blog/django-nginx-gunicorn/


This is a howto on setting up Django on a Linux (Ubuntu) system using Nginx as a reverse proxy and Gunicorn as a Django service.

django-gunicorn-nginx

The conventional way to run Django in production these days is using Apache2 and mod_wsgi. While there’s nothing wrong with that approach, I prefer Nginx. I also like to be able to control Django server separately from the web server.

There are several production-ready servers for Django. The best seem to be Gunicorn and uWSGI, and Gunicorn seems the best supported and most active project.

When running Django server separately from the web server, we need a way to start, stop and restart the Django server. A popular way for doing it in Django world is Supervisor, altough, for Ubuntu users, Upstart might be less hassle.

You probably already have a Django project you want to deploy, but for completenes’ sake, the steps here will use an empty toy “Hello World” Django project:

Preparation

First things first – you are using virtualenv, right? If not, you should.

  virtualenv --no-site-packages test
  cd test
  source bin/activate
  pip install gunicorn django
  django-admin.py startproject hello
  cd hello
  # to test the base setup works
  python manage.py runserver 0.0.0.0:8000

Gunicorn

Testing Django with Gunicorn is as simple as:

  gunicorn_django -b 0.0.0.0:8000

For production, we might want a bit more options, and we want to make sure the server is executing in the correct environment. The easiest way is to create a shell script to set it all up:

  #!/bin/bash
  set -e
  LOGFILE=/var/log/gunicorn/hello.log
  LOGDIR=$(dirname $LOGFILE)
  NUM_WORKERS=3
  # user/group to run as
  USER=your_unix_user
  GROUP=your_unix_group
  cd /path/to/test/hello
  source ../bin/activate
  test -d $LOGDIR || mkdir -p $LOGDIR
  exec ../bin/gunicorn_django -w $NUM_WORKERS 
    --user=$USER --group=$GROUP --log-level=debug 
    --log-file=$LOGFILE 2>>$LOGFILE

The number of workers is number of worker processes that will serve requests. You can set it as low as 1 if you’re on a small VPS. A popular formula is 1 + 2 * number_of_cpus on the machine (the logic being, half of the processess will be waiting for I/O, such as database). YMMV.

Don’t forget to mark the script as executable (chmod ug+x script.sh). You can run it from the command line for testing. Note that Gunicorn by default uses 127.0.0.1:8000 address (the same as Django debug server), which is fine if Nginx is on the same machine – you usually don’t want to have it wide open to anyone, and instead let Nginx handle incoming connections.

If you want to run several Django servers on the same machine, just make sure each uses a different port number.

Supervisor

Supervisor has extensive documentation, and this blog post is big already, so I’ll just point you to the official docs. The config file for running our server (/etc/supervisor/conf.d/hello.conf on Debian/Ubuntu) should look like this:

  [program:hello]
  directory = /path/to/test/hello/
  user = your_unix_user
  command = /path/to/test/hello/script.sh
  stdout_logfile = /path/to/logfile.log
  stderr_logfile = /path/to/logfile.log

Test it with supervisorctl {start,status,stop} hello (as root).

Upstart

Ubuntu alternative is Upstart, which has a similar config file (/etc/init/hello.conf). An example:

  description "Test Django instance"
  start on runlevel [2345]
  stop on runlevel [06]
  respawn
  respawn limit 10 5
  exec /path/to/test/hello/script.sh

Test it with service hello {start,status,stop} (as root).

Update 2011-11-14:For completeness of the Upstart setup configuration one has to add a soft link in /etc/init.d for a file named hello to /lib/init/upstart-job. So the following instruction should be executed after the .conf file has been created in /etc/init:

  sudo ln -s /lib/init/upstart-job /etc/init.d/hello

Update 2011-11-14: Christophe Meessen found and fixed several errors in the procedures and config files, and also provided info about the extra Upstart configuration I missed. Thanks Christophe!

Nginx

If you don’t have it set up, you should also install Nginx. The install procedure varies from system to system. On Debian and Ubuntu systems, it’s as simple as apt-get install nginx, and other Linux distributions usually have equivalent commands.

Nginx is mostly a drop-in replacement for Apache for serving static files, though there are some things to set up if you need to run PHP code as well.

For our setup, we need Nginx to serve as the reverse proxy for the upstream server(s). To do so, we add a server section to the config file:

server {
    listen   80;
    server_name example.com;
    # no security problem here, since / is alway passed to upstream
    root /path/to/test/hello;
    # serve directly - analogous for static/staticfiles
    location /media/ {
        # if asset versioning is used
        if ($query_string) {
            expires max;
        }
    }
    location /admin/media/ {
        # this changes depending on your python version
        root /path/to/test/lib/python2.6/site-packages/django/contrib;
    }
    location / {
        proxy_pass_header Server;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Scheme $scheme;
        proxy_connect_timeout 10;
        proxy_read_timeout 10;
        proxy_pass http://localhost:8000/;
    }
    # what to serve if upstream is not available or crashes
    error_page 500 502 503 504 /media/50x.html;
}

Ubuntu and Debian systems keep Nginx config files in same layout as for Apache, so the above cold be added to /etc/nginx/sites-available/hello (and enabled by symlinking from sites-enabled directory). Use nginx -t for config test and nginx -s reload to reload the configuration.

That’s it

And that’s it. The services are really quite simple to set up once you know what goes where, the setup is flexible and performant, and the server environments are isolated so it’s possible to host many different services with varying requirements on the same machine.

Have improvements on the above or your own helpful tips, or found an error in the post? Share in the comments.

23 comments

  1. gunicorn in Debian has a /etc/gunicorn.d feature (like sites-enabled) so you don’t need to mess about making your own scripts.

    Reply

    • That’s neat, thanks. Althought, that means you have to have gunicorn installed systemwide, whereas, in my example, I installed it in virtualenv. Not that installing it systemwide would neccessarily be a problem for most people, I just like having most of the stuff neatly tucked in virtualenv.

      Reply

  2. I have been meaning to learn this. Thanks.

    Reply

  3. Max Jaderberg
    June 18, 2011 at 3:32 pm

    Brilliant stuff…was really looking for a clear guide for setting up django

    Reply

  4. Why not run Django directly on uwsgi for nginx? I find it to be the far most common and well supported configuration. Performance is at least as good and there’s one less component to troubleshoot.

    Reply

    • I don’t have good arguments for whether gunicorn is better than the uwsgi combination. When I was looking for alternatives to mod_wsgi, I found both, but gunicorn did come up more often and I got the impression that more people are using it.

      Reply

  5. you could do similar setup with Cherrypy + ngingx. In fact ngingx+apache2/wsgi would also give a decent performance boost to your python/django deployments (or any other non-python apache “mods”.

    Reply

  6. We’ve been running a very similar solution for some time on FreeBSD, and it works lika charm. If you’re running it across multiple servers, you probably want to move Nginx off of each node, and run it on a central load balancer and then have separate static servers (Nginx works great for this too).

    If you want to scale it further, you can add Varnish to the equation to get some powerfull caching.

    Reply

  7. First off, great overview. That’s basically the setup I use for most of my Django projects.

    If you haven’t had the pleasure of using Fabric yet, you should definitely check it out. It’s an excellent way to manage/deploy you Django projects, including starting/restarting Gunicorn, updating you project code and doing database management; all remotely via ssh. It’s a great tool in the Django web development toolkit.

    http://docs.fabfile.org/en/1.0.1/index.html

    Reply

  8. During development, it may be preferable to run supervisord inside the virtualenv as well. Here is a small project of mine intended to make this easy: https://github.com/pilt/pewatch

    Reply

  9. Thanks for this. I’ve been shy about using Gunicorn, mostly because I’ve been using an Nginx + Apache/WSGI + Varnish trio for my django & media issues. I may look into it again for my next project. (Then again, my next project may be couchdb as my front-end server, and node.js as a back-end, so…)

    Reply

  10. Can you say a bit more about the benefits gained from using this setup over Apache? Numbers would be great, too..

    Reply

    • I didn’t want to get into whys, as the choice of the server really depends on the specific use case, so YMMV. I prefer Nginx because it’s really good at what it does (serving static assets, proxying/load balancing slower upstreams for dynamic stuff).

      I also host a bunch of apps written on various platforms (Django, Flask, Tornado, Node.js, PHP) on the same system, so I need to use some sort of a reverse proxy anyways. In such a setup, there’s no need to involve Apache too, if it’s just used for passing control on to the (Django, or PHP, …) app.

      Server benchmarks are hard to do right, but here’s a relatively recent one: http://nichol.as/benchmark-of-python-web-servers

      Reply




【直流微电网】径向直流微电网的状态空间建模与线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模与线性化方法,重点提出了一种基于耦合DC-DC变换器状态空间平均模型的建模策略。该方法通过对系统中多个相互耦合的DC-DC变换器进行统一建模,构建出整个微电网的集中状态空间模型,并在此基础上实施线性化处理,便于后续的小信号分析与稳定性研究。文中详细阐述了建模过程中的关键步骤,包括电路拓扑分析、状态变量选取、平均化处理以及雅可比矩阵的推导,最终通过Matlab代码实现模型仿真验证,展示了该方法在动态响应分析和控制器设计中的有效性。; 适合人群:具备电力电子、自动控制理论基础,熟悉Matlab/Simulink仿真工具,从事微电网、新能源系统建模与控制研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网中多变换器系统的统一建模方法;②理解状态空间平均法在非线性电力电子系统中的应用;③实现系统线性化并用于稳定性分析与控制器设计;④通过Matlab代码复现和扩展模型,服务于科研仿真与教学实践。; 阅读建议:建议读者结合Matlab代码逐步理解建模流程,重点关注状态变量的选择与平均化处理的数学推导,同时可尝试修改系统参数或拓扑结构以加深对模型通用性和适应性的理解。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值