跨過Nginx上基於uWSGI部署Django項目的坑

先說說他們的關係,Nginx和uWSGI都是Web服務器,Nginx負責靜態內容,uWSGI負責Python這樣的動態內容,兩者配合共同提供Web服務以實現提升效率和負載均衡等目的。uWSGI實現了多個協議,如WSGI,HTTP協議,還有它本身的uwsgi協議,想了解更多關於uWSGI和uwsgi協議內容能夠查閱這裏。這樣和fastcgi相似,請求和響應的流程以下:html

Request > Nginx > uWSGI > Django > uWSGI > Nginx > Responsepython

請求先交由Nginx,若是是靜態內容就本身處理了,若是是動態內容就交給uWSGI服務器,uWSGI服務器處理整個Django項目的Python代碼,響應請求,原路返回,可是與fastcgi不一樣,Nginx、uWSGI和Django能夠獨立部署,而後整合。那麼咱們從Django開始,這裏的服務器環境是Ubuntu 16.10。nginx

1. 部署Django的項目django

安裝Python和Django,Ubuntu自帶2.7和3.5版本的Python,安裝相應的Django版本,注意在Ubuntu中不一樣版本Python都有相應的命令瀏覽器

www@cloud-vm-ub01:~$ python --version
Python 2.7.12+
www@cloud-vm-ub01:~$ python3 --version
Python 3.5.2+
www@cloud-vm-ub01:~$ pip -V
pip 9.0.1 from /home/www/.local/lib/python2.7/site-packages (python 2.7)
www@cloud-vm-ub01:~$ pip3 -V
pip 9.0.1 from /home/www/.local/lib/python3.5/site-packages (python 3.5)

pip3 install django

將已經完成開發的Django項目pro(pro是Django項目名)拷貝到服務器,這裏拷貝到了www用戶(www是服務器可登陸用戶名)路徑下,最後相對路徑是~/work/project/pro,絕對路徑是/home/www/work/project/pro服務器

進入以上目錄,使用Django的內置服務器測試看看pro項目是否運行正常。網絡

python3 ./manage.py runserver 127.0.0.1:8080

2. 部署uWSGI服務器app

經過pip安裝uWSGI。負載均衡

pip3 install uwsgi

測試uWSGI是否正常,在~/work/project/pro目錄中建立一個測試用的Python文件uwsgi_test.pysocket

def application(env, start_response):
        start_response('200 OK',[('Content-Type', 'text/html')])
        #return ['Hello world'] # Python2
        return [b'Hello world'] # Python3

在pro項目路徑下,基於HTTP協議運行uWSGI,若是uWSGI安裝正常的話,能夠在瀏覽器中訪問9090端口,看到Hello world字樣

uwsgi --http 127.0.0.1:9090 --wsgi-file uwsgi_test.py

接下來啓動uWSGI加載Django項目,這裏依然使用HTTP協議,將指向具體Python文件--wsgi-file參數替換爲指向Django項目的--module參數,參數的值pro.wsgi指向~/work/project/pro/pro/wsgi.py模塊,若是正常能夠在瀏覽器http://127.0.0.1:9090端口打開了項目,可是靜態文件路徑有問題,不過不要緊後面再處理。

www@cloud-vm-ub01:~/work/project/pro$ uwsgi --http 127.0.0.1:9090 --module pro.wsgi

對於uWSGI服務器的配置,如上命令加上不少參數很是麻煩,能夠寫成配置文件的方式,在~/work/project/pro中建立一個配置文件uwsgi.ini,註釋掉參數暫時忽略,Django 1.4之前的版本須要配置如env,pythonpath等參數,這裏再也不深究了。

其中http參數用於以上測試,而與Nginx交互須要使用socket參數,即便用TCP協議,WSGI和uwsgi協議都在TCP協議之上。socket參數也能夠配置爲網絡地址,如socket=127.0.0.1:7070,但若是Nginx和uWSGI同在一個服務器上,可使用socket文件的形式。chmod-socket是爲了動態配置socket文件的權限,由於socket文件會在每次uWSGI啓動時被從新建立。

[uwsgi]
http=127.0.0.1:8000
#socket=/home/www/work/project/pro/nginx_uwsgi.socket
chdir=/home/www/work/project/pro/
#chmod-socket=664
master=true
processes=4
threads=2
module=pro.wsgi
#wsgi-file=uwsgi_test.py
#stats=127.0.0.1:9000

經過下面命令一樣能夠啓動uWSGI加載Djiango項目

uwsgi --ini uwsgi.ini

設置uwsgi爲自啓動,在Ubuntu 16. 10

3. 部署Nginx服務器

經過apt安裝Nginx

sudo apt install nginx

Nginx能夠經過如下命令控制。正常安裝和啓動Nginx後,經過http://127.0.0.1:80能夠看到Nginx的歡迎頁

sudo service nginx start
sudo service nginx stop
sudo service nginx restart

接下來修改配置Nginx配置與uWSGI服務器交互。Nginx的主要配置文件在/etc/nginx/nginx.conf和sites-enabled文件夾裏,nginx.conf是全局設置,sites-enabled文件夾裏的能夠針對不一樣站點進行配置,其中有個默認的default配置文件,該文件實際上是sites-available文件夾裏的default文件的軟連接,sites-avaliable像個倉庫,但只有sites-enabled裏的纔有效。咱們能夠將sites-enabled的default刪除,再cp一份sites-available的default到sites-enabled裏重名爲nginx-pro,同時cp /etc/nginx/uwsgi_params ~/work/project/pro裏以備nginx-pro配置文件調用。

#nginx-pro
 
upstream django{
        server unix:///home/www/work/project/pro/nginx_uwsgi.sock; # file socket
        #server 127.0.0.1:7070; # TCP socket
}


server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name 127.0.0.1; # IP or FQDN

        location /static {
                alias /home/www/work/project/pro/static;
        }

        location / {
                uwsgi_pass django;
                include /home/www/work/project/pro/uwsgi_params;
                #try_files $uri $uri/ =404;
        }
}

uwsgi_params文件是Nginx向uWSGI傳遞的參數,uwsgi_pass的意思動態內容請求都經過名爲django的upstream傳遞給uWSGI,這使用文件socket的方式,那麼與以前uwsgi.ini裏的socket參數配置一致。

4. Nginx權限問題

以上所有配置完成了,可是還有一個重要的權限問題,若是啓動uWSGI和Nginx(如下須要兩個終端窗口,由於uwsgi命令會佔據一個),會報錯

uwsgi --ini uwsgi.ini
sudo service nginx restart

在/var/log/nginx/error.log中會看到Permission denied字樣,是對home/www/work/project/pro/nginx_uwsgi.socket文件沒有讀寫權限,即運行Nginx工做進程的用戶須要socket文件的讀寫權限。

運行Nginx的工做進程的用戶在/etc/nginx/nginx.conf中有配置,是user的值www-data,但查看/etc/group發現www-data是個用戶組

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
        worker_connections 768;
        # multi_accept on;
}

咱們能夠將www用戶加入該用戶組

usermod -G www-data www

也能夠將socket文件及其上級目錄pro的用戶組改成www-data,併爲該用戶組授予讀寫權限

chown :www-data ~/home/work/project/pro
chown :www-data ~/home/work/project/pro/nginx_uwsgi.socket
chmod g+rw ~/home/work/project/pro/nginx_uwsgi.socket

5.Nginx和Django靜態文件處理

Django項目能夠正常打開,可是靜態文件引用路徑還有問題,在Django開發時Django本身能夠正確處理靜態文件的路徑,可是部署後Nginx去沒法找到靜態文件路徑。

檢查Nginx配置文件夾sites-enabled裏的nginx-pro文件,確保裏面默認的try_files要刪掉或者註釋掉,不然Nginx會所以檢查靜態文件是否存在。

將Django的靜態文件集中起來,Django爲此有專門的工具

如今Django的Settings文件中加上StATIC_ROOT,把靜態文件都集中到這個路徑下

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

執行命令

python3 ./manage.py collectstatic

這樣全部Django先後臺的靜態文件都會集中到項目文件夾pro下static中,另外nginx-pro其中一個配置location /static便可讓Nginx來處理靜態內容。

相關文章
相關標籤/搜索