Django -- 部署:nginx+uwsgi+django
相关链接
Django Document
Static Files:
nginx document
uwsgi document
- Quickstart for Python/WSGI applications
- Setting up Django and your web server with uWSGI and nginx -- 强烈推荐
概念
WSGI & uwsgi
WSGI (aka Web Server Gateway Interface
)是 Python 定义的标准(PEP333, PEP3333),定义了 Web Server 和 Python Web APP 之间通信的标准
uwsgi 用 C 语言实现了 WSGI 协议
各组件之间的关系
relationship客户端通过 HTTP协议 向web服务器请求网页,web服务器通过 WSGI协议(或 HTTP协议,socket)与 uwsgi 通信,uwsgi 调用 Python (Django)生成动态网页
为什么需要 WSGI
- 对于静态文件(HTML, CSS, JS, image)Nginx 可以直接发布
-
但对于动态生成的网页,Nginx 需要通过 WSGI 向 Django 获取;
nginx 需要服务两种内容
部署
所需组件
- Django 项目
- uwsgi
- nginx
Django 项目
# mysite/settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 项目的根目录
MEDIA_DIR = os.path.join(BASE_DIR, 'media') # 存放 Media 的目录
DEBUG = True
INSTALLED_APPS = [
'rango',
# ...
'django.contrib.staticfiles',
]
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# Static File
STATIC_URL = '/static/'
# Media File
MEDIA_ROOT = MEDIA_DIR
MEDIA_URL = '/media/'
为 Media Files 声明 URL
# mysite/urls.py
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path
urlpatterns = [
# ...
path('admin/', admin.site.urls),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
$ python manage.py runserver
HTML, Static Files 可以正常访问 Media Files 可以正常访问
在开发阶段,Django runserver 会通过
django.contrib.staticfiles
自动服务位于 app 目录下的 Static 文件和指定目录 Media 文件
nginx
systemctl status nginx # 查看状态
systemctl start nginx.service # 启动 nginx
systemctl enable nginx.service # 开机启动 nginx
nginx 欢迎页面 80 端口
nginx 配置文件
在 Django 项目根目录下创建 nginx 配置文件:mysite_nginx.conf
下面以一个项目为例:
- 项目根目录:
/root/django_projects/rango_website/
- static 文件目录:
/www/rango_website/static
- media 文件目录:
/www/rango_website/media
# mysite_nginx.conf
# the upstream component nginx needs to connect to
# nginx 与 uwsgi 通信的地址
upstream django-rango {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8002; # for a web port socket (we'll use this first)
}
# 配置一台 Web Server, 监听 8080 端口
# configuration of the server
server {
# the port your site will be served on
listen 8080;
# the domain name it will serve for
server_name demo.econfig.cn; # substitute your machine's IP address or FQDN # web Server ip地址或域名
charset utf-8;
# max upload size
client_max_body_size 75M; # adjust to taste
# 指向 Media Files 目录
# Django media
location /media {
alias /www/rango_website/media; # your Django project's media files - amend as required
}
# 指向 Static Files 目录
location /static {
alias /www/rango_website/static; # your Django project's static files - amend as required
}
# 指向 Django 项目
# Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django-rango; # 上面 upstream 定义的名字
include /root/django_projects/rango_website/uwsgi_params; # the uwsgi_params file you installed
}
}
将 nginx 目录下的 uwsgi_params
复制到 Django项目根目录
$ cp /etc/nginx/uwsgi_params ~/django_projects/rango_website/
创建链接文件:将 Django项目根目录(上面刚刚创建)的 mysite_nginx.conf
链接到 nginx 的配置目录
$ sudo ln -s django_projects/rango_website/django-rango.conf /etc/nginx/conf.d/
让 nginx 重新载入配置文件
$ nginx -s reload
将 static文件 和 media文件 放到上面指定的目录
# mysite/settings.py
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
STATIC_DIR = '/www/rango_website/static' # static 要存放的目录
# 现在不用告诉 Django : media file 在哪里,因为它交给 nginx 处理
# 但如果还要 运行 Django runserver ,则可以保留
# MEDIA_DIR = os.path.join(BASE_DIR, 'media')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
ALLOWED_HOSTS = ['demo.econfig.cn']
# Application definition
INSTALLED_APPS = [
'rango',
# ...
'django.contrib.staticfiles',
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# django 用于生成 static 文件的链接
STATIC_URL = '/static/'
STATIC_ROOT = STATIC_DIR
# 现在不用告诉 Django : media文件 在哪里
# 因为 static文件和 media文件 交给 nginx 去发布
# 但如果还要 运行 Django runserver ,则可以保留
MEDIA_URL = '/media/'
# MEDIA_ROOT = MEDIA_DIR
将 Django 项目 所有app的 static 文件收集到 /www/rango_website/static
$ python manage.py collectstatic
手动复制 media 文件
$ cp -r ./media /www/rango_website/
给 static 文件 和 media 文件访问权限
# chmod -R 755 /www
哎,终于好了,static 文件和 media 文件都交给 nginx 发布;人在塔在
static 文件可以正常访问
但首页却无法访问,因为动态页面要由 Django 生成,而我们还没启用 uwsgi
502 服务器端错误uwsgi :nginx 和 django 之间的通信媒介
注:这里的 djagno 项目是事先在 pipenv 虚拟环境创建的
$ pipenv install uwsgi # 安装uwsgi
$ pipenv shell # 进入 pipenv 虚拟环境
创建 uwsgi 配置文件:mysite_uwsgi.ini
[uwsgi]
socket = :8002 # uswgi 端口
chdir = /root/django_projects/rango_website # django项目根目录
module = rango_website.wsgi # django项目的 wsgi 模块 rango_website/wsgi.py
processes = 4 # 工作进程数
threads = 2 # 线程数
stats = 127.0.0.1:9002 # 进程统计信息
virtualenv = /root/.local/share/virtualenvs/rango_website-e68KS5mW/ # 虚拟环境位置
# 1个 uwsgi 主进程
# 4个 处理请求的进程
# 每个工作进程有2个线程
啊?我忘记虚拟环境的路径是什么了...
$ pipenv --venv # 查看虚拟环境路径
/root/.local/share/virtualenvs/rango_website-e68KS5mW
启动 uswgi
$ uwsgi rango_uwsgi.ini
uwsgi 启动成功
访问首页
relationship
错误
访问 static 文件和 media 文件 出现 404 错误
反问三连
- nginx 配置文件中 static 文件和 media文件 的路径正确吗
-
重新载入 nginx 配置文件了吗
nginx -s reload
-
static 文件 和 media 文件放到 指定目录了吗
$ python manage.py collectstatic
$ cp -r ./media /www/rango_website/
访问 static 文件和 media 文件 出现 403 错误 (拒绝访问)
目录权限给了吗 # chmod -R 755 /www