使用uWSGI和nginx在服務(wù)器上部署Django(官網(wǎng)教程+注解)

Setting up Django and your web server with uWSGI and nginx

寫在最前:
此文章是直接把uWSGI的教程弄下來了,這是最靠譜的教程了,但是自己弄的時(shí)候還是遇到了一些坑,最終通過自己的摸索終于完成了服務(wù)器的搭建,特寫此文幫助各位和我一樣的新手快速爬坑.
Setting up Django and your web server with uWSGI and nginx — uWSGI 2.0 documentation
感謝@Corssin先生的提點(diǎn)和他的教程帶我入門,請(qǐng)關(guān)注微信公眾號(hào)“Crossin的編程教室”.

環(huán)境:Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-38-generic x86_64)
[騰訊云服務(wù)器,默認(rèn)系統(tǒng)是16,給升級(jí)了]
Python 3.6.6
(自帶的,Ubuntu 16自帶3.5應(yīng)該沒有影響)

以后文章中有需要注意的地方都會(huì)用這種形式寫出來

請(qǐng)先行了解Linux的用戶逞带、用戶組和文件權(quán)限的相關(guān)概念,不然到后面你會(huì)很痛苦.
關(guān)于Django,建議現(xiàn)在自己的電腦上按照官網(wǎng)的教程完整走一遍再來學(xué)習(xí)部署服務(wù)器.
所有的操作不建議在~目錄下進(jìn)行,先切換到/目錄(看你方便,新手還是在/下最省事,就是不建議在任何用戶目錄里,不然權(quán)限問題又是個(gè)大坑).

This tutorial is aimed at the Django user who wants to set up a production web server. It takes you through the steps required to set up Django so that it works nicely with uWSGI and nginx. It covers all three components, providing a complete stack of web application and server software.

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.

Some notes about this tutorial

Note

This is a tutorial. It is not intended to provide a reference guide, never mind an exhaustive reference, to the subject of deployment.

nginx and uWSGI are good choices for Django deployment, but they are not the only ones, or the ‘official’ ones. There are excellent alternatives to both, and you are encouraged to investigate them.

The way we deploy Django here is a good way, but it is not the only way; for some purposes it is probably not even the best way.

It is however a reliable and easy way, and the material covered here will introduce you to concepts and procedures you will need to be familiar with whatever software you use for deploying Django. By providing you with a working setup, and rehearsing the steps you must take to get there, it will offer you a basis for exploring other ways to achieve this.

Note

This tutorial makes some assumptions about the system you are using.

It is assumed that you are using a Unix-like system, and that it features an aptitude-like package manager. However if you need to ask questions like “What’s the equivalent of aptitude on Mac OS X?”, you’ll be able to find that kind of help fairly easily.

While this tutorial assumes Django 1.4 or later, which will automatically create a wsgi module in your new project, the instructions will work with earlier versions. You will though need to obtain that Django wsgi module yourself, and you may find that the Django project directory structure is slightly different.

Concept

A web server faces the outside world. It can serve files (HTML, images, CSS, etc) directly from the file system. However, it can’t talk directly to Django applications; it needs something that will run the application, feed it requests from web clients (such as browsers) and return responses.

A Web Server Gateway Interface - WSGI - does this job. WSGI is a Python standard.

uWSGI is a WSGI implementation. In this tutorial we will set up uWSGI so that it creates a Unix socket, and serves responses to the web server via the uwsgi protocol. At the end, our complete stack of components will look like this:

the web client <-> the web server <-> the socket <-> uwsgi <-> Django

Before you start setting up uWSGI

virtualenv

Make sure you are in a virtualenv for the software we need to install (we will describe how to install a system-wide uwsgi later):

cd /
virtualenv uwsgi-tutorial #嘗試sudo python3 -m venv uwsgi-tutorial
cd uwsgi-tutorial
source bin/activate

個(gè)人認(rèn)為虛擬環(huán)境是必須的,因?yàn)榈箶?shù)第二步有需要用到這個(gè)虛擬環(huán)境的地方.
如果你用python3 而且需要用python3命令來啟動(dòng)的更是需要
嘗試sudo python3 -m venv uwsgi-tutorial
如果缺少東西的話會(huì)提示你,按照說明安裝了就可以了.
記得切換到/目錄喲

Django

Install Django into your virtualenv, create a new project, and cd into the project:

同樣在/目錄下喲

pip install Django
django-admin.py startproject mysite
cd mysite

About the domain and port

In this tutorial we will call your domain example.com. Substitute your own FQDN or IP address.

Throughout, we’ll be using port 8000 for the web server to publish on, just like the Django runserver does by default. You can use whatever port you want of course, but I have chosen this one so it doesn’t conflict with anything a web server might be doing already.

Basic uWSGI installation and configuration

Install uWSGI into your virtualenv

pip install uwsgi

Of course there are other ways to install uWSGI, but this one is as good as any. Remember that you will need to have Python development packages installed. In the case of Debian, or Debian-derived systems such as Ubuntu, what you need to have installed is pythonX.Y-dev, where X.Y is your version of Python.

如果安裝uwsgi報(bào)錯(cuò)的話就要安裝開發(fā)包,??

Basic test

Create a file called test.py:

這里我是吧這個(gè)文件放到了/mysite/目錄下了,看你自己

# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3
    #return ["Hello World"] # python2

Note

Take into account that Python 3 requires bytes().

Run uWSGI:

uwsgi --http :8000 --wsgi-file test.py

使用云服務(wù)器記得把這個(gè)端口放通哦

The options mean:

  • http :8000: use protocol http, port 8000
  • wsgi-file test.py: load the specified file, test.py
    This should serve a ‘hello world’ message directly to the browser on port 8000. Visit:
http://example.com:8000

to check. If so, it means the following stack of components works:

the web client <-> uWSGI <-> Python

Test your Django project

Now we want uWSGI to do the same thing, but to run a Django site instead of the test.py module.

If you haven’t already done so, make sure that your mysite project actually works:

python manage.py runserver 0.0.0.0:8000

And if that works, run it using uWSGI:

uwsgi --http :8000 --module mysite.wsgi
  • module mysite.wsgi: load the specified wsgi module
    Point your browser at the server; if the site appears, it means uWSGI is able to serve your Django application from your virtualenv, and this stack operates correctly:
the web client <-> uWSGI <-> Django

Now normally we won’t have the browser speaking directly to uWSGI. That’s a job for the webserver, which will act as a go-between.

一個(gè)老問題,如果訪問頁面沒有小火箭而是報(bào)錯(cuò),請(qǐng)把你的服務(wù)器ip(看報(bào)錯(cuò)說明)填入setting.py文件中.

Basic nginx

Install nginx

sudo apt-get install nginx
sudo /etc/init.d/nginx start    # start nginx

And now check that nginx is serving by visiting it in a web browser on port 80 - you should get a message from nginx: “Welcome to nginx!”. That means these components of the full stack are working together:

the web client <-> the web server

If something else is already serving on port 80 and you want to use nginx there, you’ll have to reconfigure nginx to serve on a different port. For this tutorial though, we’re going to be using port 8000.

Configure nginx for your site

You will need the uwsgi_params file, which is available in the nginx directory of the uWSGI distribution, or from https://github.com/nginx/nginx/blob/master/conf/uwsgi_params

uwsgi_params復(fù)制到你的工程目錄,也就是/mysite/

Copy it into your project directory. In a moment we will tell nginx to refer to it.

Now create a file called mysite_nginx.conf in the etc_nginx_sites-available directory, and put this in it:

這里叫你在/etc/nginx/sites-available/下創(chuàng)建這個(gè)文件,我不建議你這樣做,而是按下面文章說的方法,“把它放在你的工程目錄里”/mysite/mysite_nginx.conf

# 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)這里不要改喲,最后也用不到這個(gè)
}

# 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

    # Django media
    location /media  {
        alias /path/to/your/mysite/media;  # your Django project's media files - amend as required*****這里要改*****,如果按照我說的來也就是alias /mysite/media
    }

    location /static {
        alias /path/to/your/mysite/static; # your Django project's static files - amend as required*****這里要改***** alias /mysite/static
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed*****這里要改***** include /mysite/uwsgi_params
    }
}

This conf file tells nginx to serve up media and static files from the filesystem, as well as handle requests that require Django’s intervention. For a large deployment it is considered good practice to let one server handle static/media files, and another handle Django applications, but for now, this will do just fine.

Symlink to this file from _etc_nginx/sites-enabled so nginx can see it:

sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

使用軟連接 ln -s時(shí)最好第一個(gè)參數(shù)使用絕對(duì)路徑,不然容易出錯(cuò),以后無論在哪里也都推薦這樣做,即使你已經(jīng)在當(dāng)前文件夾
sudo ln -s /mysite/mysite_nginx.conf /etc/nginx/sites-enabled

Deploying static files

Before running nginx, you have to collect all Django static files in the static folder. First of all you have to edit mysite/settings.py adding:

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

and then run

python manage.py collectstatic

Basic nginx test

Restart nginx:

sudo /etc/init.d/nginx restart

To check that media files are being served correctly, add an image called media.png to the /path/to/your/project/project/media directory, then visit http://example.com:8000/media/media.png - if this works, you’ll know at least that nginx is serving files correctly.

It is worth not just restarting nginx, but actually stopping and then starting it again, which will inform you if there is a problem, and where it is.

nginx and uWSGI and test.py

Let’s get nginx to speak to the “hello world” test.py application.

uwsgi --socket :8001 --wsgi-file test.py

This is nearly the same as before, except this time one of the options is different:

  • socket :8001: use protocol uwsgi, port 8001
    nginx meanwhile has been configured to communicate with uWSGI on that port, and with the outside world on port 8000. Visit:

http://example.com:8000/

to check. And this is our stack:

the web client <-> the web server <-> the socket <-> uWSGI <-> Python

Meanwhile, you can try to have a look at the uswgi output at http://example.com:8001 - but quite probably, it won’t work because your browser speaks http, not uWSGI, though you should see output from uWSGI in your terminal.

Using Unix sockets instead of ports

So far we have used a TCP port socket, because it’s simpler, but in fact it’s better to use Unix sockets than ports - there’s less overhead.

Edit mysite_nginx.conf, changing it to match:

server unix:///path/to/your/mysite/mysite.sock; # for a file socket ***改成這樣** server unix:///mysite/mysite.sock
# server 127.0.0.1:8001; # for a web port socket (we'll use this first)

and restart nginx.

Run uWSGI again:

uwsgi --socket mysite.sock --wsgi-file test.py

This time the socket option tells uWSGI which file to use.

Try http://example.com:8000/ in the browser.

這里一般開始就容易出錯(cuò)了,請(qǐng)看官網(wǎng)的解決辦法

If that doesn’t work

Check your nginx error log(_var_log_nginx_error.log). If you see something like:

connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission
denied)

then probably you need to manage the permissions on the socket so that nginx is allowed to use it.

Try:

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=666 # (very permissive)

親測還是需要666權(quán)限,應(yīng)為nginx默認(rèn)沒有用戶,所以最后的6權(quán)限還是需要的,而不是4
or:

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 # (more sensible)

You may also have to add your user to nginx’s group (which is probably www-data), or vice-versa, so that nginx can read and write to your socket properly.

It’s worth keeping the output of the nginx log running in a terminal window so you can easily refer to it while troubleshooting.

Running the Django application with uwsgi and nginx

Let’s run our Django application:

uwsgi --socket mysite.sock --module mysite.wsgi --chmod-socket=664

還是用666權(quán)限喲

Now uWSGI and nginx should be serving up not just a “Hello World” module, but your Django project.

Configuring uWSGI to run with a .ini file

We can put the same options that we used with uWSGI into a file, and then ask uWSGI to run with that file. It makes it easier to manage configurations.

Create a file called mysite_uwsgi.ini:

同樣也放在/mysite/

# mysite_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
# 這里就是放工程路徑  /mysite/
chdir           = /path/to/your/project
# Django's wsgi file
# wsgi模塊,他是在/mysite/mysite/wsgi.py,所以就改成mysite.wsgi
module          = project.wsgi
# the virtualenv (full path)
# 這里放python的虛擬環(huán)境, /uwsgi-tutorial
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改成/mysite/mysite.sock
socket          = /path/to/your/project/mysite.sock
# ... with appropriate permissions - may be needed
# chmod-socket需要取消注釋,并且改成666
# chmod-socket    = 664
# clear environment on exit
vacuum          = true

And run uswgi using this file:

uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file

Once again, test that the Django site works as expected.

這樣來測試一般不會(huì)有什么問題

Install uWSGI system-wide

So far, uWSGI is only installed in our virtualenv; we’ll need it installed system-wide for deployment purposes.

Deactivate your virtualenv:

deactivate

and install uWSGI system-wide:

sudo pip install uwsgi

# Or install LTS (long term support).
pip install https://projects.unbit.it/downloads/uwsgi-lts.tar.gz

千萬記得加sudo或者sudo python3 -m pip install uwsgi
不加sudo就會(huì)安裝到~/.local 這類的文件夾下,然后就是一堆權(quán)限問題

The uWSGI wiki describes several installation procedures. Before installing uWSGI system-wide, it’s worth considering which version to choose and the most apppropriate way of installing it.

Check again that you can still run uWSGI just like you did before:

uwsgi --ini mysite_uwsgi.ini # the --ini option is used to specify a file

用sudo安裝的uwsgi一般不會(huì)出問題

Emperor mode

“皇帝模式”,我喜歡這個(gè)名字
uWSGI can run in ‘emperor’ mode. In this mode it keeps an eye on a directory of uWSGI config files, and will spawn instances (‘vassals’) for each one it finds.

Whenever a config file is amended, the emperor will automatically restart the vassal.

# 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

You may need to run uWSGI with sudo:

sudo uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data

The options mean:

  • emperor: where to look for vassals (config files)
  • uid: the user id of the process once it’s started
  • gid: the group id of the process once it’s started
    Check the site; it should be running.

現(xiàn)在開始服務(wù)器報(bào)502了是吧,我就因?yàn)檫@個(gè)折騰好久
仔細(xì)看命令執(zhí)行完的輸出里面有一句Bind() …. permission denied之類的.
是因?yàn)?code>--uid www-data --gid www-data用了www-data用戶和組,
解決辦法

  1. 切換到/目錄,用ls -al看看你的文件的權(quán)限
    出現(xiàn)這個(gè)問題應(yīng)該是/mysite/這個(gè)文件夾對(duì)www-data用戶沒有開放寫的權(quán)限
    先用sudo chgrp -R www-data /mysite來改下這個(gè)文件夾的組,
    再用sudo chmod 775 /mysite這里沒有-R參數(shù)咯,開啟www-data對(duì)這個(gè)文件夾寫的權(quán)限
    以后也是,發(fā)現(xiàn)需要權(quán)限的就用這個(gè)方法來逐步放開,不要圖省事一次全部放開777權(quán)限,這樣不安全

Make uWSGI startup when the system boots

The last step is to make it all happen automatically at system startup time.

For many systems, the easiest (if not the best) way to do this is to use the rc.local file.

Edit /etc/rc.local and add:

/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid www-data --gid www-data --daemonize /var/log/uwsgi-emperor.log

before the line “exit 0”.

And that should be it!

Further configuration

It is important to understand that this has been a tutorial, to get you started. You do need to read the nginx and uWSGI documentation, and study the options available before deployment in a production environment.

Both nginx and uWSGI benefit from friendly communities, who are able to offer invaluable advice about configuration and usage.

nginx

General configuration of nginx is not within the scope of this tutorial though you’ll probably want it to listen on port 80, not 8000, for a production website.

You should also configure a separate nginx location block for serving non-Django files. For example, it’s inefficient to serve static files via uWSGI. Instead, serve them directly from Nginx and completely bypass uWSGI.

uWSGI

uWSGI supports multiple ways to configure it. See uWSGI’s documentation and examples.

Some uWSGI options have been mentioned in this tutorial; others you ought to look at for a deployment in production include (listed here with example settings):

env = DJANGO_SETTINGS_MODULE=mysite.settings # set an environment variable
safe-pidfile = /tmp/project-master.pid # create a pidfile
harakiri = 20 # respawn processes taking more than 20 seconds
limit-as = 128 # limit the project to 128 MB
max-requests = 5000 # respawn processes after serving 5000 requests
daemonize = /var/log/uwsgi/yourproject.log # background the process & log
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末骇钦,一起剝皮案震驚了整個(gè)濱河市绣溜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沙兰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翘魄,死亡現(xiàn)場離奇詭異鼎天,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)暑竟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門斋射,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人但荤,你說我怎么就攤上這事罗岖。” “怎么了腹躁?”我有些...
    開封第一講書人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵桑包,是天一觀的道長。 經(jīng)常有香客問我纺非,道長哑了,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任烧颖,我火速辦了婚禮弱左,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘炕淮。我一直安慰自己拆火,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開白布涂圆。 她就那樣靜靜地躺著们镜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪润歉。 梳的紋絲不亂的頭發(fā)上模狭,一...
    開封第一講書人閱讀 51,215評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音卡辰,去河邊找鬼胞皱。 笑死邪意,一個(gè)胖子當(dāng)著我的面吹牛九妈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雾鬼,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼萌朱,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了策菜?” 一聲冷哼從身側(cè)響起晶疼,我...
    開封第一講書人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤酒贬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后翠霍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锭吨,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年寒匙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了零如。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锄弱,死狀恐怖考蕾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情会宪,我是刑警寧澤肖卧,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站掸鹅,受9級(jí)特大地震影響塞帐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巍沙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一壁榕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赎瞎,春花似錦牌里、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敞临,卻和暖如春态辛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挺尿。 一陣腳步聲響...
    開封第一講書人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來泰國打工奏黑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人编矾。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓熟史,卻偏偏與公主長得像,于是被迫代替她去往敵國和親窄俏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹂匹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354