写在最前:
此文章是直接把uWSGI的教程弄下来了,这是最靠谱的教程了,但是自己弄的时候还是遇到了一些坑,最终通过自己的摸索终于完成了服务器的搭建,特写此文帮助各位和我一样的新手快速爬坑.
Setting up Django and your web server with uWSGI and nginx — uWSGI 2.0 documentation
感谢@Corssin先生的提点和他的教程带我入门,请关注微信公众号“Crossin的编程教室”.
环境:Ubuntu 18.04.1 LTS (GNU/Linux 4.15.0-38-generic x86_64)
[腾讯云服务器,默认系统是16,给升级了]
Python 3.6.6
(自带的,Ubuntu 16自带3.5应该没有影响)
以后文章中有需要注意的地方都会用这种形式写出来
~//
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
sudo python3 -m venv uwsgi-tutorial/
Django
cd
/
pip install Django
django-admin.py startproject mysite
cd mysite
About the domain and port
example.com
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
pythonX.Y-dev
如果安装uwsgi报错的话就要安装开发包,⬆️
Basic test
test.py
/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
bytes()
Run uWSGI:
uwsgi --http :8000 --wsgi-file test.py
使用云服务器记得把这个端口放通哦
The options mean:
http :8000wsgi-file test.py
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
test.py
mysite
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
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.
一个老问题,如果访问页面没有小火箭而是报错,请把你的服务器ip(看报错说明)填入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
uwsgi_paramsnginx
uwsgi_params/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//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)这里不要改哟,最后也用不到这个
}
# 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/
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
media.png/path/to/your/project/project/media directory
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
test.py
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
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.
mysite_nginx.conf
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
socket
这里一般开始就容易出错了,请看官网的解决办法
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权限,应为nginx默认没有用户,所以最后的6权限还是需要的,而不是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权限哟
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.
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的虚拟环境, /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.
这样来测试一般不会有什么问题
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 python3 -m pip install uwsgi
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一般不会出问题
Emperor mode
“皇帝模式”,我喜欢这个名字
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:
emperoruidgid
--uid www-data --gid www-data/ls -al/mysite/sudo chgrp -R www-data /mysitesudo chmod 775 /mysite
Make uWSGI startup when the system boots
The last step is to make it all happen automatically at system startup time.
rc.local
/etc/rc.local
/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