Django是一个高效,灵活,动态的Web应用开发框架。在Django刚开始流行的时候,大多数推荐的Django运行环境配置都是基于使用mod_wsgi模块的Apache。而近来大家所推荐的关于更高级的Django运行环境配置则更加高效和具有弹性,但同时也更加复杂,使用的工具包括:Nginx, Gunicorn, virtualenv, supervisord和PostgreSQL.
在这篇文章中我会解释如何在Linux上将这些组件组合起来,成为一个能够运行django的服务器。
预置条件:
首先我假设你有一台具有Root权限的服务器,我正在使用的Linux发行版是debian7,所以以下的内容也同样适用于Ubuntu或者其他基于Debian的Linux发行版。如果你是在使用基于RPM的Linux发行版(比如说CentOS),你需要用yum替换掉以下命令中提到的apt-get,如果你在使用FreeBSD,你可以使用Ports安装这些组件。
如果你暂时没有服务器,那么我推荐你使用Linode的VPS,虽然价格稍贵,但是各项服务及服务器性能都是最佳的。如果你使用我提供的链接购买Linode,我会获得一点推荐佣金。
同样的我也假设你已经将你的域名通过DNS指向了你的服务器IP,而你的域名是example.com。
升级系统:
首先我们需要确定我们的系统是否是最新的。
$ sudo apt-get update $ sudo apt-get upgrade
PostgreSQL
在基于Debian的系统上运行以下命令安装PostgreSQL
$ sudo apt-get install postgresql postgresql-contrib
创建一个数据库以及拥有该数据库权限的用户
$ sudo su - postgres postgres@django:~$ createdb hello postgres@django:~$ createuser -P Enter name of role to add: hello_django Enter password for new role: Enter it again: Shall the new role be a superuser? (y/n) n Shall the new role be allowed to create databases? (y/n) n Shall the new role be allowed to create more new roles? (y/n) n postgres@django:~$ psql psql (9.1.9) Type "help" for help. postgres=# GRANT ALL PRIVILEGES ON DATABASE hello TO hello_django; GRANT postgres=# \q postgres@django:~$ logout $
对于习惯使用Mysql的同学,这里也可以安装Mysql来替换PostgreSQL,运行以下命令安装Mysql
$ sudo apt-get install mysql-server
Mysql的安全设置
$ mysql_secure_installation
按照提示一步一步进行即可
如果你需要修改Mysql的Root密码,那么运行以下命令:
$ dpkg-reconfigure mysql-server-5.0
进入Mysql控制台
$ mysql -uroot -p
创建数据库和拥有该数据库权限的用户
CREATE DATABASE hello; CREATE USER 'example_user' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON hello.* TO 'example_user'; exit
安装virtualenv然后为你的django应用创建一个运行环境
Virtualenv是一个能够允许你在系统中创建隔离的Python环境的工具。这使你能够在同一台服务器上运行需要不同设置的应用程序(例如,一个基于Django1.2,另一个基于Django1.5)。Virtualenv在debian系统上很容易安装:
$ sudo apt-get install python-virtualenv
为你的应用创建并激活一个虚拟环境
因为django的特性,你可以在任何地方创建你的虚拟环境目录,我这里是在/webapps/目录下创建,如果你习惯使用类似于/var/www/的目录或者其他目录,只需要替换掉/webapps/就行。
$ cd /webapps/ $ virtualenv hello_django New python executable in hello_django/bin/python Installing distribute.............................done Installing pip........................................done $ cd hello_django $ source bin/activate (hello_django) $
看到上面的提示符时,就表明你的虚拟环境已经激活,然后你就可以在里面安装Django了。在安装的时候你可以看到pip已经被安装到了虚拟环境中,所以你可以直接使用pip来安装需要的python组件。
(hello_django) $ pip install django Downloading/uppacking django (...) Installing collected packages: django (...) Successfully installed django Cleaning up...
现在你的Django虚拟环境应该已经可以使用了,创建一个空的Django项目试试看。
(hello_django) $ django-admin.py startproject hello
你可以使用开发服务器来测试一下
(hello_django) $ cd hello (hello_django) $ python manage.py runserver example.com:8000
使用http://example.com:8000来访问服务器试一下,在这之前,请确保你的服务器防火墙开了8000端口。
设置PostgreSQL在Django下工作
要在Django下使用PostgreSQL,你需要在虚拟环境中安装psycopg2数据库适配器,这一步需要原生扩展编译,如果没法找到头文件、使用libpq(用来与Postgres通信的库)链接C程序的静态库和创建Python模块的python开发库(python-dev package),编译将会失败。所以我们必须先安装这些依赖包,然后再使用PIP安装psycopg2。
安装依赖包
$ sudo apt-get install libpq-dev python-dev
安装psycopg2数据库适配器
(hello_django) $ pip install psycopg2
在你的django项目settings.py文件中修改数据库连接设置,这一步在默认的settings.py文件中有详细的注释,就不在此列出了。
使用Django初始化数据库
(hello_django) $ python manage.py syncdb
P.S. 如果你使用了MySQL作为数据库,那么你需要安装Python-MySQL来使python程序能够访问mysql,具体安装部骤网上很多,可以自行google一下。
Gunicorn
在生产环境中我们肯定不会使用Django的单线程开发服务器,而是使用一个专用的应用服务器,叫作Gunicorn。
在你的应用虚拟环境中安装Gunicorn
(hello_django) $ pip install gunicorn Downloading/unpacking gunicorn Downloading gunicorn-0.17.4.tar.gz (372Kb): 372Kb downloaded Running setup.py egg_info for package gunicorn Installing collected packages: gunicorn Running setup.py install for gunicorn Installing gunicorn_paster script to /webapps/hello_django/bin Installing gunicorn script to /webapps/hello_django/bin Installing gunicorn_django script to /webapps/hello_django/bin Successfully installed gunicorn Cleaning up...
Ok,现在你已经这安装好了Gunicorn,尝试测试一下Gunicorn和Django是否可以正常工作
(hello_django) $ gunicorn_django --bind example.com:8001
在浏览器中访问http://example.com:8001,看看django是否正常工作。
到现在为止,Gunicorn已经安装好,并且已经可以和django一起正常工作了,接下来让我们来做一些设置让gunicorn更加好用一些。我喜欢设置一些参数,所以我们可以把它们放在一个BASH脚本里,我将这个脚本保存在bin/gunicorn_start。
bin/gunicorn_start
#!/bin/bash NAME="hello_app" # Name of the application DJANGODIR=/webapps/hello_django/hello # Django project directory SOCKFILE=/webapps/hello_django/run/gunicorn.sock # we will communicte using this unix socket USER=michal # the user to run as GROUP=michal # the group to run as NUM_WORKERS=3 # how many worker processes should Gunicorn spawn DJANGO_SETTINGS_MODULE=hello.settings # which settings file should Django use echo "Starting $NAME" # Activate the virtual environment cd $DJANGODIR source ../bin/activate export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE export PYTHONPATH=$DJANGODIR:$PYTHONPATH # Create the run directory if it doesn't exist RUNDIR=$(dirname $SOCKFILE) test -d $RUNDIR || mkdir -p $RUNDIR # Start your Django Unicorn # Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon) exec ../bin/gunicorn_django \ --name $NAME \ --workers $NUM_WORKERS \ --user=$USER --group=$GROUP \ --log-level=debug \ --bind=unix:$SOCKFILE
接下来将gunicorn_start脚本设置为可执行
$ chmod u+x bin/gunicorn_start
运行以下命令来测试gunicorn_start是否正常
$ ./bin/gunicorn_start Starting hello_app 2013-06-09 21:14:07 [2792] [INFO] Starting gunicorn 0.17.4 2013-06-09 21:14:07 [2792] [DEBUG] Arbiter booted 2013-06-09 21:14:07 [2792] [INFO] Listening at: unix:/webapps/hello_django/run/gunicorn.sock (2792) 2013-06-09 21:14:07 [2792] [INFO] Using worker: sync 2013-06-09 21:14:07 [2798] [INFO] Booting worker with pid: 2798 2013-06-09 21:14:07 [2799] [INFO] Booting worker with pid: 2799 2013-06-09 21:14:07 [2800] [INFO] Booting worker with pid: 2800
注意gunicorn_start中的参数设置,你需要修改里面的参数以适合你自己的设置。
根据经验(as a rule-of-thumb),通过以下公式来设置 –worker(NUM_WORKERS):
2 * CPUs + 1。
–name(NAME)参数指定你如何在程序中识别你的应用。默认值为gunicorn,如果你不修改的话,当你的服务器中有多个gunicorn驱动的应用时会使应用难以区分。
为了使–name参数起作用,你需要安装一个叫做setproctitle的Python模块。在你的系统中安装python-dev依赖包然后再安装setproctitle。
$ sudo apt-get install python-dev
(hello_django) $ pip install setproctitle
现在你可以将进程都列出来,你应该可以看到哪个gunicorn进程属于哪个应用。
$ ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND (...) michal 16124 0.0 1.9 56168 9860 ? S 15:37 0:00 gunicorn: master [hello_app] michal 16130 0.0 4.5 73520 23004 ? S 15:37 0:00 gunicorn: worker [hello_app] michal 16131 0.0 4.5 73496 23004 ? S 15:37 0:00 gunicorn: worker [hello_app] michal 16132 0.0 4.5 73504 23004 ? S 15:37 0:00 gunicorn: worker [hello_app]
使用Supervisor来启动和监测应用
现在gunicorn_start脚本已经可以正常工作了,下面我们需要让它在开机时自启动,或者在某些情况下能够正常重启。我们使用supervisor来处理这些任务。
安装非常简单:
$ sudo apt-get install supervisor
当supervisor安装好后,你可以在/etc/supervisor/conf.d目录下创建配置文件来管理gunicorn。下面是为hello这个应用创建的一个配置文件
/etc/supervisor/conf.d/hello.conf
[program:hello] command = /webapps/hello_django/bin/gunicorn_start ; Command to start app user = michal ; User to run as stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log ; Where to write log messages redirect_stderr = true ; Save stderr in the same log
当然你还可以设置其他的选项,但是基础配置已经足够了。
保存好后,告诉supervisor重新读取配置文件并更新(这将会启动你刚注册的应用)
$ sudo supervisorctl reread hello: available $ sudo supervisorctl update hello: added process group
你也可以使用supervisor检查你的应用的状态,或者启动、停止应用。
$ sudo supervisorctl status hello hello RUNNING pid 18020, uptime 0:00:50 $ sudo supervisorctl stop hello hello: stopped $ sudo supervisorctl start hello hello: started $ sudo supervisorctl restart hello hello: stopped hello: started
现在,你的应用将可以在系统重启之后自动启动,或者在由于某些原因发生错误时自动重启。
Nginx
现在是时候为我们的应用和静态文件配置Nginx服务了,安装并启动Nginx:
$ sudo apt-get install nginx $ sudo service nginx start
在浏览器中访问你的服务器(http://example.com)。你应该可以看到nginx的欢迎界面-“Welcome to nginx”。
每一个Nginx虚拟服务器配置文件应该放在/etc/nginx/sites-available/目录下,你可以选择将你想要启用的站点配置文件符号连接至/etc/nginx/sites-enabled/目录下。
在/etc/nginx/sites-available/目录下创建一个新的nginx服务器配置文件。一般来说文件应该包含下面这些配置,如果你需要更详细的配置说明,请看这里:
https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf
/etc/nginx/sites-available/hello
upstream hello_app_server { # fail_timeout=0 means we always retry an upstream even if it failed # to return a good HTTP response (in case the Unicorn master nukes a # single worker for timing out). server unix:/webapps/hello_django/run/gunicorn.sock fail_timeout=0; server { listen 80; server_name example.com; client_max_body_size 4G; access_log /webapps/hello_django/logs/nginx-access.log; error_log /webapps/hello_django/logs/nginx-error.log; location /static/ { alias /webapps/hello_django/static/; } location /media/ { alias /webapps/hello_django/media/; } location / { # an HTTP header important enough to have its own Wikipedia entry: # http://en.wikipedia.org/wiki/X-Forwarded-For proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # enable this if and only if you use HTTPS, this helps Rack # set the proper protocol for doing redirects: # proxy_set_header X-Forwarded-Proto https; # pass the Host: header from the client right along so redirects # can be set properly within the Rack application proxy_set_header Host $http_host; # we don't want nginx trying to do something clever with # redirects, we set the Host: header above already. proxy_redirect off; # set "proxy_buffering off" *only* for Rainbows! when doing # Comet/long-poll stuff. It's also safe to set if you're # using only serving fast clients with Unicorn + nginx. # Otherwise you _want_ nginx to buffer responses to slow # clients, really. # proxy_buffering off; # Try to serve static files from nginx, no point in making an # *application* server like Unicorn/Rainbows! serve static files. if (!-f $request_filename) { proxy_pass http://hello_app_server; break; } } # Error pages error_page 500 502 503 504 /500.html; location = /500.html { root /webapps/hello_django/static/; } } 重启Nginx
$ sudo service nginx restart
现在再访问http://example.com你应该要以看到django的欢迎界面了。
如果你在以上的配置中发现任何问题,可以在评论中留言。
最终的目录结构:
/webapps/hello_django/ ├── bin <= Directory created by virtualenv │ ├── activate <= Environment activation script │ ├── django-admin.py │ ├── gunicorn │ ├── gunicorn_django │ ├── gunicorn_start <= Script to start application with Gunicorn │ └── python ├── hello <= Django project directory, add this to PYTHONPATH │ ├── manage.py │ ├── project_application_1 │ ├── project_application_2 │ └── hello <= Project settings directory │ ├── __init__.py │ ├── settings.py <= hello.settings - settings module Gunicorn will use │ ├── urls.py │ └── wsgi.py ├── include │ └── python2.7 -> /usr/include/python2.7 ├── lib │ └── python2.7 ├── lib64 -> /webapps/proxydemo/lib ├── logs <= Application logs directory │ ├── gunicorn_supervisor.log │ ├── nginx-access.log │ └── nginx-error.log ├── media <= User uploaded files folder ├── run │ └── gunicorn.sock └── static <= Collect and serve static files from here
卸载django应用
如果你需要卸载掉你的django应用,按照以下步骤
移除Nginx sites-enabled文件夹中的虚拟服务器配置文件
$ sudo rm /etc/nginx/sites-enabled/hello_django
重启Nginx
$ sudo service nginx restart
如果你不想再次使用该应用,你可以从sites-available文件夹中删除掉真实的配置文件
$ sudo rm /etc/nginx/sites-available/hello_django
使用supervisor停止应用
$ sudo supervisorctl stop hello
从supervisor的控制脚本目录中移除应用
$ sudo rm /etc/supervisor/conf.d/hello.conf
如果你真的不想再使用这个应用了,哥们,你肯定是受到什么打击了。你可以在webapps中移除整个目录:
$ sudo rm -rf /webapps/hello_django
本文暂时没有评论,来添加一个吧(●'◡'●)