Django+Ubuntu+Nginx+Gunicorn應用部署
Django是Python語言中最受歡迎的全棧式Web框架之一,過去部署Django應用一般採用Apache+mod_wsgi,但是由於有了Nginx出色的效能表現,Django也有了更先進的部署方式,比較常用的一種部署方案是Nginx+Gunicorn。 接下來我會詳細完整地介紹一個符合生產條件標準的部署過程。
前提條件
假設你對Linux有基本的瞭解,而且擁有一臺root許可權的主機。我使用的Linux發行版是Ubuntu12.04。你也可以選擇其他Linux發行版(如:CentOS、Fedora),如果你手頭沒有伺服器,那麼我推薦使用非常便宜的VPS伺服器DigitalOcean
更新系統
$ sudo apt-get update $ sudo apt-get upgrade $ sudo apt-get install python-dev
安裝MySQL
$ sudo apt-get install mysql-server
安裝過程中會提示輸入資料庫密碼,安裝成功後建立一個MySQL新使用者,並賦予許可權
#以管理員身份登入 mysql -uroot -p #選擇mysql use mysql #建立使用者名稱和設定密碼 create user 'test_user'@'localhost' identified by 'password' #建立資料庫 create database test_db #授予test_user操作test_db的所有許可權 grant all privileges on test_db.* to[email protected] identified by 'password' #使所有操作生效 flush privileges
安裝Virtualenv
Virtualenv可以在系統中建立一個獨立的Python環境,多個應用之間彼此不受影響,這樣不同的應用使用的依賴庫就不會相互衝突(比如一個應用是基於Django1.5,另一個應用可以用Django1.6)。
$ pip install virtualenv
我們把應用虛擬環境建立在/webapps目錄下面,
$ cd /webapps/ $ virtualenv hello_django New python executable in hello_django/bin/python Installing Setuptools....................................done. Installing Pip...........................................done. $ cdhello_django $ source bin/activate # 啟用 (hello_django) $ # 注意`$`符號前的hello_django表明你已經在這個新的python虛擬環境中 (hello_django) $ pip install django # 安裝django (hello_django) $ django-admin.py startproject hello # 建立一個空的django專案hello
用開發模式測試一下專案是否可以正常執行
(hello_django) $ cd hello (hello_django) $ python manage.py runserver localhost:80 Validating models... 0 errors found January 17, 2014 - 10:34:13 Django version 1.6.1, using settings 'hello.settings' Starting development server at http://localhost:80/ Quit the server with CONTROL-C.
此時你應該可以正常訪問:http://localhost了。
更新settings檔案
Django 使用MySQL作為後端儲存需要使用MySQL-python
資料庫介面卡,但是它需要依賴本地擴充套件庫python-dev
,libmysqlclient-dev
,所以先安裝依賴庫
$ sudo apt-get install python-dev libmysqlclient-dev
安裝 MySQL-python
(hello_django) $pip install mysql-python
在settings.py中配置資料庫資訊
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test_db', 'USER': 'test_user', 'PASSWORD': 'password', 'HOST': 'localhost', 'PORT': '', # Set to empty string for default. } }
django初始化資料庫,預設Django會建立一些資料表
(hello_dango) $ python manage.py syncdb
為應用建立系統使用者
雖然Django有完善的安全追蹤記錄,但是如果應用對伺服器資源的訪問限制在自己的範圍內,可以避免無謂的入侵危害,因此我們的web應用應該使用有限制許可權的使用者來執行這個web應用。
為應用建立一個使用者,名字叫做hello
,附給系統組叫webapps
。
$ sudo groupadd --system webapps $ sudo useradd --system --gid webapps --home /webapps/hello_django hello
安裝Gunicorn
在生產環境下我們就不應該使用Django自帶的單執行緒的開發伺服器,Gunicorn就是很好的選擇。
(hello_django) $ pip install gunicorn
安裝成功後,現在你可以通過一下命令測試下你的django應用能否執行在gunicorn上面。
(hello_django) $ gunicorn hello.wsgi:application --bind 0.0.0.0:8001
現在你應該可以從http://localhost:8001 訪問Gunicorn伺服器。Gunicorn安裝好後,接下來再寫一個bash指令碼做一些配置使之用起來更方便。 檔案儲存為bin/gunicorn_start.sh
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 | #!/bin/bash NAME='hello_app' #應用的名稱 DJANGODIR=/webapps/hello_django/hello #django專案的目錄 SOCKFILE=/webapps/hello_django/run/gunicorn.sock #使用這個sock來通訊 USER=hello #執行此應用的使用者 GROUP=webapps #執行此應用的組 NUM_WORKERS=3 #gunicorn使用的工作程序數 DJANGO_SETTINGS_MODULE=hello.settings #django的配置檔案 DJANGO_WSGI_MODULE=hello.wsgi #wsgi模組 echo "starting $NAME as `whoami`" #啟用python虛擬執行環境 cd $DJANGODIR source ../bin/activate export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE export PYTHONPATH=$DJANGODIR:$PYTHONPATH #如果gunicorn.sock所在目錄不存在則建立 RUNDIR=$(dirname $SOCKFILE) test -d $RUNDIR || mkdir -p $RUNDIR #啟動Django exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \ --name $NAME \ --workers $NUM_WORKERS \ --user=$USER --GROUP=$GROUP \ --log-level=debug \ --bind=unix:$SOCKFILE |
使用者hello
將運新這個應用,那麼要把這個應用的目錄的許可權交給hello
$ sudo chown -R hello:users /webapps/hello_django $ sudo chmod -R g+w /webapps/hello_django $ sudo chmod u+x bin/gunicorn_start.sh
如果你還不是組users
的成員,使用下面命令:
$ sudo usermod -a -G users `whoami`
現在就可以切換到使用者hello
來執行這段指令碼:
$sudo su - hello $bin/gunicorn_start.sh Starting hello_app as hello 2014-01-17 15:59:25 [10724] [INFO] Starting gunicorn 18.0 2014-01-17 15:59:25 [10724] [DEBUG] Arbiter booted 2014-01-17 15:59:25 [10724] [INFO] Listening at: unix:/webapps/hello_django/run/gunicorn.sock (10724) 2014-01-17 15:59:25 [10724] [INFO] Using worker: sync 2014-01-17 15:59:25 [10735] [INFO] Booting worker with pid: 10735 2014-01-17 15:59:25 [10736] [INFO] Booting worker with pid: 10736 2014-01-17 15:59:25 [10737] [INFO] Booting worker with pid: 10737
- --workers 設定的個數規則是:2*CPUs+1。因此單核CPU機器的程序數設定為3個。
- --name 預設是
gunicorn
,置頂後,可以通過top
或ps
檢視到,唯一標識其程序。
使用Supervisor啟動、監控應用
指令碼現在準備就緒,我們需要確保系統能夠自動啟動或者重啟,因為系統可能會由於某些原因導致異常終止,這個任務就交給supervisor,它的安裝也非常簡單:
$ sudo apt-get insatll supervisor
安裝後,在/etc/supervisor/conf.d/
目錄下建立配置檔案/etc/supervisor/conf.d/hello.conf
,用來啟動、監視應用程式。
[program:hello] command = /webapps/hello_django/bin/gunicorn_start.sh ; Command to start app user = hello ; User to run as stdout_logfile = /webapps/hello_django/logs/gunicorn_supervisor.log ; Where to write log messages redirect_stderr = true
建立檔案儲存日誌:
$ mkdir -p /webapps/hello/logs $ touch /webapps/hello_django/logs/gunicorn_supervisor.log
配置好了之後,supervisor重新載入配置檔案
$ sudo supervisorctl reread hello: available $ sudo supervisorctl update hello: added process group
同時你還可以檢查app的狀態、啟動、停止、重啟
$ sudo aupervisorctl status hello
hello RUNNING
$ sudo supervisorctl stop hello
hello: stopped
$ sudo supervisorctl start hello
hello: started
$sudo supervisorctl restart hello
hello:stoped
hello:started
現在應用可以在系統重啟或者某些原因崩潰後自動重啟了。
配置Nginx
Nginx作為反向代理程式
$ sudo apt-get install nginx $ sudo /etc/init.d/nginx start
每個Nginx虛擬伺服器應該是通過一個在/etc/nginx/sites-available
目錄下的檔案描述的,為了使之生效需要在/etc/nginx/sites-enbled
做一個符號連線。建立配置檔案/etc/nginx/sites-available/hello
,內容如下:
upstream hello_app_server { server unix:/webapps/hello_django/run/gunicorn.sock fail_timeout=0; } server { listen 80; server_name localhost; 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 / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; 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/; } }
建立符號連結:
$ sudo ln -s /etc/nginx/sites-available/hello /etc/nginx/sites-enabled/hello
重啟Nginx:
$ sudo /etc/init.d/nginx restart
所有配置基本完成了,現在你就可以看到django的歡迎介面了。
解除安裝Django應用
如果你需要解除安裝這個專案,那麼可以按照如下步驟徹底清除
移除虛擬伺服器從Nginx的sites-enabled
目錄:
$ sudo rm /etc/nginx/sites-enabled/hello_django
重啟Nginx:
$ sudo /etc/init.d/nginx restart
如果以後都不打算使用這個專案了,那麼可以從site-available
目錄刪除配置檔案
$ sudo rm /etc/nginx/sites-available/hello_django
用Supervisor停掉應用:
$ sudo supervisorctl stop hello
從supervisor的控制指令碼目錄中移除配置:
$ sudo rm /etc/supervisor/conf.d/hello.conf
最後可以把整個應用的目錄刪除:
$ sudo rm -r /webapps/hello_django
總結
如果你是一步一步根據這個教程來操作的話,那麼整個目錄結構應該是如下:
/webapps/hello_django/ ├── bin <= virtualenv建立的目錄 │ ├── activate <= Environment activation script │ ├── django-admin.py │ ├── gunicorn │ ├── gunicorn_django │ ├── gunicorn_start.sh <= 用Gunicorn啟動應用的指令碼 │ └── python ├── hello <= 專案的根目錄,把他新增到 PYTHONPATH │ ├── manage.py │ ├── project_application_1 │ ├── project_application_2 │ └── hello <= 專案的配置目錄 │ ├── __init__.py │ ├── settings.py <= hello.settings - settings模組, Gunicorn需要使用 │ ├── urls.py │ └── wsgi.py <= hello.wsgi - WSGI module,Gunicorn使用 ├── include │ └── python2.7 -> /usr/include/python2.7 ├── lib │ └── python2.7 ├── lib64 -> /webapps/hello_django/lib ├── logs <= 專案的日子目錄 │ ├── gunicorn_supervisor.log │ ├── nginx-access.log │ └── nginx-error.log ├── media <= 使用者檔案上傳目錄 ├── run │ └── gunicorn.sock └── static <= 專案的靜態資源目錄
所有步驟經過自己操作驗證通過,如果你在配置過程中有任何疑問,毫不猶豫給我留言。
關注公眾號「Python之禪」(id:vttalk)獲取最新文章