记录一下使用Nginx + uwsgi部署Django项目
关于域名和端口
在这个教程中,我们将假设你的域名为 example.com
。用你自己的FQDN或者IP地址来代替。
从头到尾,我们将使用8000端口作为web服务器的公开端口,就像Django runserver默认的那样。当然,你可以使用任何你想要的端口,但是我已经选了这个,因此,它不会与web服务器可能已经选择的任何端口冲突。
基本的uWSGI安装和配置
把uWSGI安装到你的virtualenv中
pip install uwsgi
当然,有其他安装uWSGI的方式,但这种方式如其他方式一样棒。记住,你将需要安装Python开发包。对于Debian,或者Debian衍生系统,例如Ubuntu,你需要安装的是 pythonX.Y-dev
,其中,X.Y是你Python的版本。
基础测试
创建一个名为 test.py
文件:
# test.py def application(env, start_response): start_response('200 OK', [('Content-Type','text/html')]) return [b"Hello World"] # python3 # return ["Hello World"] # python2
运行uWSGI:
uwsgi --http :8000 --wsgi-file test.py
选项表示:
http :8000 -->
使用http协议,端口8000wsgi-file test.py -->
加载指定的文件,test.py
当浏览器访问8000端口时,这将直接提供一个’hello world’消息。 访问:
http://example.com:8000
来看一看。如果是这样,那么意味着以下的组件栈正常:
the web client <-> uWSGI <-> Python
测试你的Django项目
现在,我们想让uWSGI做同样的事,但是返回一个Django站点而不是 test.py
模块。
如果你还没有这样做,那么请确保你的 mysite
项目实际上正常工作:
python manage.py runserver 0.0.0.0:8000
而如果正常,则使用uWSGI来运行它:
uwsgi --http :8000 --module mysite.wsgi # mysite.wsgi 就是你项目下的wsgi文件,例如 app01.wsgi
将你的浏览器指向该服务器;如果站点出现,那么意味着uWSGI可以为你虚拟环境中的Django应用服务,而这个栈工作正常:
现在,通常我们不会让浏览器直接与uWSGI通信。那是web服务器的工作,这是个穿针引线的活。
使用Nginx
安装nginx
ubuntu:
sudo apt-get install nginx sudo /etc/init.d/nginx start # start nginx
现在,通过在一个web浏览器上通过端口80访问它,来检查nginx是否正常 - 你应该会从nginx获得一个消息:”Welcome to nginx!”. 那意味着整个栈的这些模块都能一起正常工作:
如果有其他的东东已经提供端口80的服务了,并且你想要在那里使用nginx,那么你将必须重新配置nginx来提供另一个端口的服务。但是,在这个教程中,我们将使用端口8000。
为你的站点配置nginx
一、创建uwsgi_params文件
你会需要 uwsgi_params 文件,可用在uWSGI发行版本的 nginx
目录下,或者从https://github.com/nginx/nginx/blob/master/conf/uwsgi_params 找到。
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
将其拷贝到你的项目目录中。一会儿,我们将告诉nginx引用它。
二、设置nginx.conf配置文件,这里是自定义配置文件
现在,创建一个名为mysite_nginx.conf的文件,然后将这个写入到它里面:
# the upstream component nginx needs to connect to upstream django { # server unix:///path/to/your/mysite/mysite.sock; # 这里是通过socket方式访问django项目,也是我们的最终目的。mysite.sock文件会自动创建,我们只需要指定前面的路径到我们项目即可 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; # IP地址或者域名 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 } location /static { alias /path/to/your/mysite/static; # your Django project's static files - amend as required } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass django; # 指定django include /path/to/your/mysite/uwsgi_params; # 这里是我们刚刚第一步创建的uwsgi_params文件,指定路径 } }
这个配置文件告诉nginx提供来自文件系统的媒体和静态文件。
将这个文件链接到/etc/nginx/sites-enabled,然后告诉Nginx使用我们创建的配置文件:
sudo ln -s ~/path/to/your/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/
配置完后重启nginx
/usr/local/nginx/sbin/nginx -t # 检查配置 /usr/local/nginx/sbin/nginx -s reload # 重新加载重启
三、使用Unix socket而不是端口
目前,我们使用了一个TCP端口socket,因为它简单些,但事实上,使用Unix socket会比端口更好 - 开销更少。
编辑 mysite_nginx.conf
, 修改它以匹配:
# the upstream component nginx needs to connect to upstream django { server unix:///var/www/project/project/mysite.sock; # 指定到我们的项目目录下即可,mysite.sock会自动创建 # server 127.0.0.1:8001; # for a web port socket (we'll use this first) }
然后重启nginx
/usr/local/nginx/sbin/nginx -s stop # 停止 /usr/local/nginx/sbin/nginx # 开启
再次运行uWSGI:
uwsgi --socket mysite.sock --wsgi-file test.py
在浏览器中尝试访问http://example.com:8000/。
四、使用uwsgi和nginx运行Django应用
在配置nginx.conf配置文件后,我们就可以进行下一步对django项目的操作了:
在项目目录下创建一个uwsgi.ini文件,这里主要是通过ini运行uwsgi,里面就是一些配置参数,为了方便我们这里把参数都写到了uwsgi.ini文件下然后添加下面配置:
[uwsgi] # Django-related settings , chdir = /var/www/progect/ # Django's wsgi file,application 对象的模块 module = application .wsgi # process-related settings master = true # maximum number of worker processes processes = 10 # the socket (use the full path to be safe socket = /var/www/project/WeChatPM/mysite.sock chmod-socket = 666 # clear environment on exit master = true vacuum = true max-requests = 5000 processes = 4 # 设置日志目录,后台运行 daemonize=/var/www/project/logs/uwsgi/uwsgi.log #配置存放主进程的进程号文件和状态文件 pidfile= /var/www/project/logs/uwsgi/uwsgi.pid stats= /var/www/project/logs/uwsgi/uwsgi.stats
这里特定于Django的选项是:
chdir
:需要在Python的导入路径上的目录的路径 - 即包含该mysite
包的目录。module
:要使用的WSGI模块 - 可能mysite.wsgi
是startproject
创建的模块。env
:至少应该包含DJANGO_SETTINGS_MODULE
。home
:项目virtualenv的可选路径。
然后使用这个文件运行uswgi:
uwsgi --ini uwsgi.ini # 指定到uwsgi.ini的路径
启动uwsgi:uwsgi --ini uwsgi.ini 停止uwsgi:uwsgi --stop uwsgi.pid 重新加载配置:uwsgi --reload uwsgi.pid
再次,测试Django站点是否如预期工作。
如何设置uwsgi后台运行:
需要在mysite_uwsgi.ini
配置文件中添加
daemonize = /var/www/project/hello/uwsgi.log
这样就会吧日志打印到uwsgi.log中。
通过查 nginx
的access_log 和 error_log 进行调试错误
配置参数说明:
[uwsgi] # 项目目录 chdir=/opt/project_teacher/teacher/ # 指定项目的application module=teacher.wsgi:application # 进程个数 workers=5 pidfile=/opt/project_teacher/script/uwsgi.pid # 指定IP端口 http=192.168.31.123:8080 # 指定静态文件 static-map=/static=/opt/test_project/teacher/static # 启动uwsgi的用户名和用户组 uid=root gid=root # 启用主进程 master=true # 自动移除unix Socket和pid文件当服务停止的时候 vacuum=true # 序列化接受的内容,如果可能的话 thunder-lock=true # 启用线程 enable-threads=true # 设置自中断时间 harakiri=30 # 设置缓冲 post-buffering=4096 # 设置日志目录 daemonize=/opt/project_teacher/script/uwsgi.log # 指定sock的文件路径 socket=/opt/project_teacher/script/uwsgi.sock
server { # 这个server标识我要配置了 listen 80; # 我要监听那个端口 server_name 127.0.0.1 域名; # 你访问的路径,IP或域名 access_log /var/log/nginx/access.log main; # Nginx日志配置 charset utf-8; # Nginx编码 gzip on; # 启用压缩,这个的作用就是给用户一个网页,比如3M压缩后1M这样传输速度就会提高很多 gzip_types text/plain application/x-javascript text/css text/javascript application/x-httpd-php application/json text/json image/jpeg image/gif image/png application/octet-stream; # 支持压缩的类型 error_page 404 /404.html; # 错误页面 error_page 500 502 503 504 /50x.html; # 错误页面 # 指定项目路径uwsgi location / { # 这个location就和咱们Django的url(r'^admin/', admin.site.urls), include uwsgi_params; # 导入一个Nginx模块他是用来和uWSGI进行通讯的 uwsgi_connect_timeout 30; # 设置连接uWSGI超时时间 uwsgi_pass unix:/opt/project_teacher/script/uwsgi.sock; # 指定uwsgi的sock文件所有动态请求就会直接丢给他 } # 指定静态文件路径 location /static/ { alias /opt/project_teacher/teacher/static/; index index.html index.htm; }