django deplop by virtualenv + gunicorn + nginx + supervisor

今天尝试了一下在一台机器上去安装不同版本的python、django
发现原来linux上有个类似模拟虚拟环境的东西啊virtualenv
就尝试自己在这个虚拟环境里搭建了一套自django1.9.2 python2.7 然后用gunicorn做web服务器、supervisor去管理进程、nginx去做外部转发和访问,这期间参考了国外和国内的一些大牛写的文章,在这里首先表示感谢
我也确实是按照这个步骤自己完成了一套这样的服务

第一步:安装虚拟环境的库

1
2
3
4
5
6
7
sudo pip install virtualenv

Downloading/unpacking virtualenv
Downloading virtualenv-15.0.3-py2.py3-none-any.whl (3.5MB): 3.5MB downloaded
Installing collected packages: virtualenv
Successfully installed virtualenv
Cleaning up...

第二步:创建虚拟环境

1
2
3
virtualenv bugenv
New python executable in /Users/tataufo/todaysay_env/bin/python
Installing setuptools, pip, wheel...done.

第三步:进入虚拟环境

1
2
3
root@recall:/home/www# cd bugenv/
root@recall:/home/www/bugenv# source bin/activate
(bugenv)root@recall:/home/www/bugenv #激活环境,这个每次在重新登陆服务器的时候都需要激活

第三步:安装django和gunicorn

1
2
sudo pip install django==1.9.2
sudo pip install gunicorn

第四步:创建django项目和django app

django-admin.py startproject bugproject
python manages.py startapp bugapp

1
2
3
4
5
6
7
8
复制
(bugenv)root@recall:/home/www/bugenv# ls
bin include lib local
(bugenv)root@recall:/home/www/bugenv# mkdir djcode
(bugenv)root@recall:/home/www/bugenv# cd djcode/
(bugenv)root@recall:/home/www/bugenv/djcode# django-admin.py startproject bugproject
(bugenv)root@recall:/home/www/bugenv/djcode# cd bugproject/
(bugenv)root@recall:/home/www/bugenv/djcode/bugproject# python manage.py startapp bugapp

第五步:设置django 的settings.py文件
添加app,最后结果如下

1
2
3
4
5
6
7
8
9
10
11
12

INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# add app
'bugapp',
'gunicorn',
)

第六步:运行gunicorn

1
2
3
4

(bugenv)root@recall:/home/www/bugenv/djcode/bugproject# pwd
/home/www/bugenv/djcode/bugproject
(bugenv)root@recall:/home/www/bugenv/djcode/bugproject# gunicorn bugproject.wsgi:application -b 127.0.0.1:11000

在这里说下,如果你想同时启动多个端口和设置允许访问的IP可以如下
更多设置参考 http://docs.gunicorn.org/en/stable/settings.html

1
2
3
(bugenv)root@recall:/home/www/bugenv/djcode/bugproject# gunicorn bugproject.wsgi:application -b 127.0.0.1:11000 -b 127.0.0.1:11001 -b 127.0.0.1:11002 -b 127.0.0.1:11003

(bugenv)root@recall:/home/www/bugenv/djcode/bugproject# gunicorn bugproject.wsgi:application --forwarded-allow-ips '10.166.80.90:8000, 10.65.100.20:9000'

第七步:使用supervisor去管理gunicorn的运行
先创建一个脚本去启动django服务,就叫gunicorn_start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#!/bin/bash

NAME="bugproject" # Name of the application
DJANGODIR=/home/www/bugenv/djcode/bugproject # Django project directory
SOCKFILE=/home/www/bugenv/djcode/run/gunicorn.sock # we will communicte using this unix socket
USER=root # the user to run as
GROUP=root # the group to run as
NUM_WORKERS=4 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=bugproject.settings # which settings file should Django use
DJANGO_WSGI_MODULE=bugproject.wsgi # WSGI module name

PORT=11000
SERVER_NAME=0.0.0.0

echo "Starting $NAME as `whoami`"

# 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_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=$SERVER_NAME:$PORT \
--log-level=debug \
--log-file=-
~

以后就用这个脚本去运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ sudo chmod u+x bin/gunicorn_start
$ . gunicorn_start

Starting bugproject as hello
2016-06-09 14:21:45 [10724] [INFO] Starting gunicorn 18.0
2016-06-09 14:21:45 [10724] [DEBUG] Arbiter booted
2016-06-09 14:21:45 [10724] [INFO] Listening at: unix:/home/www/bugenv/djcode/run/gunicorn.sock (10724)
2016-06-09 14:21:45 [10724] [INFO] Using worker: sync
2016-06-09 14:21:45 [10735] [INFO] Booting worker with pid: 10735
2016-06-09 14:21:45 [10736] [INFO] Booting worker with pid: 10736
2016-06-09 14:21:45 [10737] [INFO] Booting worker with pid: 10737

^C (CONTROL-C to kill Gunicorn)

2016-06-09 14:21:48 [10736] [INFO] Worker exiting (pid: 10736)
2016-06-09 14:21:48 [10735] [INFO] Worker exiting (pid: 10735)
2016-06-09 14:21:48 [10724] [INFO] Handling signal: int
2016-06-09 14:21:48 [10737] [INFO] Worker exiting (pid: 10737)
2016-06-09 14:21:48 [10724] [INFO] Shutting down: Master

第八步:安装supervisor

1
$ sudo aptitude install supervisor

Supervisor可以管理多个服务,因此你可以为不同的服务创建不同的配置文件

1
2
cd /etc/supervisor/conf.d
vim hello.conf

文件内容:

1
2
3
4
5
6
[program:hello]
command = /home/www/bugenv/djcode/gunicorn_start ; Command to start app
user = hello ; User to run as
stdout_logfile = /home/www/bugenv/djcode/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true ; Save stderr in the same log
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ; Set UTF-8 as default encoding

创建日志文件

1
2
hello@django:~$ mkdir -p /home/www/bugenv/djcode/logs/
hello@django:~$ touch /home/www/bugenv/djcode/logs/gunicorn_supervisor.log

测试supervisorctl

1
2
3
4
$ sudo supervisorctl reread
hello: available
$ sudo supervisorctl update
hello: added process group

supervisor重启、查看状态、停止操作

1
2
3
4
5
6
7
8
9
$ 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

1
2
$ sudo install nginx
$ sudo service nginx start

配置nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

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:/home/www/bugenv/djcode/run/gunicorn.sock fail_timeout=0;
}

server {

listen 80;
server_name example.com;

client_max_body_size 4G;

access_log /home/www/bugenv/djcode/logs/nginx-access.log;
error_log /home/www/bugenv/djcode/logs/nginx-error.log;

location /static/ {
alias /home/www/bugenv/djcode/static/;
}

location /media/ {
alias /home/www/bugenv/djcode/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 /home/www/bugenv/djcode/static/;
}
}

重启

1
2
$ nginx  -c /etc/nginx/nginx.conf #设置加载配置文件
$ sudo service nginx restart

最后附上如何卸载各个服务(这里就不翻译了):

Uninstalling the Django application

If time comes to remove the application, follow these steps.

Remove the virtual server from Nginx sites-enabled folder:

1
$ sudo rm /etc/nginx/sites-enabled/hello_django

Restart Nginx:

1
$ sudo service nginx restart

If you never plan to use this application again, you can remove its config file also from the sites-available directory

1
$ sudo rm /etc/nginx/sites-available/hello_django

Stop the application with Supervisor:

1
$ sudo supervisorctl stop hello

Remove the application from Supervisor’s control scripts directory:

1
$ sudo rm /etc/supervisor/conf.d/hello.conf

If you never plan to use this application again, you can now remove its entire directory from webapps:

1
$ sudo rm -r /webapps/hello_django

感谢该文章作者:
http://michal.karzynski.pl/blog/2013/06/09/django-nginx-gunicorn-virtualenv-supervisor/

希望可以帮到你,Best wishes