一. 簡(jiǎn)介
Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design.
nginx (pronounced engine-x) is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server.
A Web Server Gateway Interface - WSGI - does this job. WSGI is a Python standard.
二. 組件概覽
the web client <-> the web server <-> the socket <-> uwsgi <-> Django
nginx充當(dāng)the web server形纺,響應(yīng)處理靜態(tài)資源的請(qǐng)求贷币,并將動(dòng)態(tài)資源的請(qǐng)求通過(guò)socket以u(píng)wsgi協(xié)議轉(zhuǎn)發(fā)給uWSG處理搜骡,uWSG則是運(yùn)行django項(xiàng)目的web服務(wù)鱼辙。
三. 具體步驟
逐步搭建,方便排查問(wèn)題谋币。以下步驟若未特殊聲明寨昙,則均在云服務(wù)器上執(zhí)行掠归。
1. virtualenv
方法一:
安裝virtualenv
sudo apt-get install virtualenv
創(chuàng)建和激活virtualenv
virtualenv env --no-site-packages --python=python3
source env/bin/activate
--no-site-packages 表示不使用系統(tǒng)已經(jīng)安裝的第三方庫(kù)
--python指定項(xiàng)目用到的python版本
方法二:
使用python3內(nèi)置venv
$ python3 -m venv envpy3
2. 測(cè)試uwsgi
將uwsgi安裝到virtualenv中。激活virtualenv再執(zhí)行
pip install uwsgi
新建文件test.py并寫(xiě)入以下內(nèi)容
# test.py
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"] # python3
#return ["Hello World"] # python2
運(yùn)行uwsgi
uwsgi --http :8000 --wsgi-file test.py
訪問(wèn)127.0.0.1:8000
查看是否成功卢鹦,若成功說(shuō)明以下組件連接成功
the web client <-> uWSGI <-> Python
3. 測(cè)試django項(xiàng)目
在本機(jī)django的項(xiàng)目根目錄執(zhí)行以下命令臀脏,生成項(xiàng)目依賴清單requirements.txt
pip freeze > requirements.txt
用scp命令將django項(xiàng)目傳到云服務(wù)器
scp [option] <localfile> <username>@<host>:<remote-file-location>
示例:
scp -r /home/user/hello_django user@x.x.x.x:/home/user/
激活virtualenv劝堪,切換到項(xiàng)目根目錄下安裝依賴
pip install -r requirements.txt
運(yùn)行django
python manage.py runserver 0.0.0.0:8000
如果運(yùn)行成功,再測(cè)試使用uwsgi運(yùn)行django
uwsgi --http :8000 --module hello_django.wsgi
--module 指定django模塊
如果成功揉稚,說(shuō)明以下組件連接成功
the web client <-> uWSGI <-> Django
4. 測(cè)試nginx
安裝
sudo apt-get install nginx
啟動(dòng)
sudo systemctl start nginx
nginx默認(rèn)監(jiān)聽(tīng)80端口秒啦,所以可以訪問(wèn)127.0.0.1:80
測(cè)試是否成功。
nginx安裝之后搀玖,會(huì)默認(rèn)創(chuàng)建www-data用戶和組余境,并以www-data身份運(yùn)行nginx(可以在/etc/nginx/nginx.conf首行查看或修改)。為了避免文件訪問(wèn)權(quán)限問(wèn)題灌诅,修改django項(xiàng)目的用戶組
sudo chown -R :www-data hello_django
5. 部署靜態(tài)資源
在django項(xiàng)目的settings.py文件添加
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
然后執(zhí)行
python manage.py collectstatic
即可將項(xiàng)目的靜態(tài)資源統(tǒng)一收集到項(xiàng)目根目錄下的static文件夾中芳来。
在/etc/nginx/sites-available/目錄下,新建hello_django.conf并寫(xiě)入以下內(nèi)容猜拾,將static路徑替換成上面的項(xiàng)目的static目錄路徑
# mysite_nginx.conf
# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 8000;
# the domain name it will serve for
server_name example.com; # substitute your machine's IP address or FQDN
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# 開(kāi)啟gzip
gzip on;
# 啟用gzip壓縮的最小文件即舌,小于設(shè)置值的文件將不會(huì)壓縮
gzip_min_length 1k;
# gzip 壓縮級(jí)別,1-10挎袜,數(shù)字越大壓縮的越好顽聂,也越占用CPU時(shí)間,后面會(huì)有詳細(xì)說(shuō)明
gzip_comp_level 2;
# 進(jìn)行壓縮的文件類型盯仪。javascript有多種形式紊搪。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
# 是否在http header中添加Vary: Accept-Encoding全景,建議開(kāi)啟
gzip_vary on;
# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";
# Django media
# location /media {
# alias /path/to/your/mysite/media; # your Django project's media files - amend as required
# expires 30d;
# }
location /static {
alias /path/to/your/mysite/static; # your Django project's static files - amend as required
# enable cache
expires 30d;
}
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
}
并創(chuàng)建軟鏈接到/etc/nignx/sites-enabled目錄
sudo ln -s /etc/nginx/sites-available/hello_django.conf /etc/nginx/sites-enabled/
重加載nginx
nginx -s reload
然后訪問(wèn)127.0.0.1:8000/static/xxx/xxx.png
耀石,若成功說(shuō)明靜態(tài)資源部署成功。
若訪問(wèn)失敗可查看nginx錯(cuò)誤日志(/var/log/nginx/error.log)爸黄,Permission denied問(wèn)題請(qǐng)將static目錄加入到www-data用戶組娶牌。
6. 連接nginx和uwsgi
以--socket方式運(yùn)行django項(xiàng)目,并將端口改成nginx中配置的8001端口
uwsgi --socket :8001 --module hello_django.wsgi
然后訪問(wèn)127.0.0.1:8000
查看測(cè)試nginx的動(dòng)態(tài)轉(zhuǎn)發(fā)是否成功馆纳。
若成功,則所有組件的連接都成功了
the web client <-> the web server <-> the socket <-> uWSGI <-> Python
7. 使用Unix sockets替換uwsgi的端口
nignx和uwsgi間通過(guò)socket端口連接雖然簡(jiǎn)單汹桦,但是不是最佳方式鲁驶,應(yīng)改用Unix sockets。
修改hello_django.conf
server unix:///path/to/your/mysite/mysite.sock; # for a file socket
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)
指定使用Unix sockets時(shí)創(chuàng)建的sock文件舞骆,如
server unix:///home/www-data/hello_django/hello_django.sock; # for a file socket
然后改以u(píng)nit socket方式運(yùn)行django
uwsgi --socket /home/www-data/hello_django/hello_django.sock --module hello_django.wsgi --chmod-socket=666
--chmod-socket是為了避免hello_django.sock文件的權(quán)限問(wèn)題
然后訪問(wèn)查看是否成功钥弯。
8. 以.ini文件方式運(yùn)行uwsgi
創(chuàng)建文件 hello_django_uwsgi.ini
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /path/to/your/project
# Django's wsgi file
module = project.wsgi
# the virtualenv (full path)
home = /path/to/virtualenv
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 10
# the socket (use the full path to be safe
socket = /path/to/your/project/mysite.sock
# ... with appropriate permissions - may be needed
chmod-socket = 666
# clear environment on exit
vacuum = true
然后指定文件啟動(dòng)uwsgi
uwsgi --ini hello_django_uwsgi.ini # the --ini option is used to specify a file
9. 將uwsgi配置成service并設(shè)置開(kāi)機(jī)自啟
退出virtualenv
deactivate
將uwsgi安裝到系統(tǒng)環(huán)境
sudo pip3 install uwsgi
然后用系統(tǒng)環(huán)境的uwsgi測(cè)試
uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file
在/etc/systemd/system目錄,新建文件hello_django.service
[Unit]
Description=hello django uwsgi web service
After=syslog.target
[Service]
Type=simple
ExecStart= /usr/local/bin/uwsgi --ini /path/to/your/hello_django.ini
Restart=always
StandardError=syslog
[Install]
WantedBy=multi-user.target
配置完成后督禽,reload一下systemd脆霎,即成功添加了hello_django的service
$ sudo systemctl daemon-reload
啟動(dòng)
systemclt start hello_django
設(shè)置開(kāi)機(jī)自啟
systemctl enable hello_django
systemd還可以監(jiān)控服務(wù)進(jìn)程,代替supervisor第三方庫(kù)狈惫。
10. 其他
以Emperor模式啟動(dòng)uwsgi睛蛛,該模式下,會(huì)監(jiān)視uwsgi的配置文件,當(dāng)配置文件被修改后忆肾,會(huì)自動(dòng)重啟uwsgi下對(duì)應(yīng)的web服務(wù)荸频。
# create a directory for the vassals
sudo mkdir /etc/uwsgi
sudo mkdir /etc/uwsgi/vassals
# symlink from the default config directory to your config file
sudo ln -s /path/to/your/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/
# run the emperor
uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
啟動(dòng)
sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data
在hello_django.service的配置文件中修改啟動(dòng)的shell命令
/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi-emperor.log
參考文章
https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html