目录
django项目部署
settings中的首先要确保这两项修改过来:
DEBUG = False#防止一些数据或者敏感数据被泄漏
ALLOWED_HOSTS = ['*']#保证每个人都能访问
需要上传django项目文件,重建虚拟的python环境
- pip3.6 install virtualenv
- virtualenv --python=/usr/bin/python3.6 /home/loverweb/venv
- source /home/loverweb/venv/bin/activate
参考:https://blog.csdn.net/duxin_csdn/article/details/83341922
关于之前项目开发使用的库,可以构建requirements.txt文件,然后在服务器商直接通过 pip install -r requirements.txt,进行快速的下载
配置好静态文件和媒体文件
注意,要配置好静态文件和媒体文件的ROOT路径,不然nginx会出错,如ngnix的error.log有一条报错:
2020/11/11 17:32:04 [error] 24872#24872: *60 open() "/home/Django/static/rest_framework/js/default.js" failed (2: No such file or directory), client: 111.42.148.86, server: www.XXX.fun, request: "GET /static/rest_framework/js/default.js HTTP/1.1", host: "www.XXX.fun", referrer: "http://www.XXXX.fun/goods/get_classes/"
配置静态文件步骤如下
-
首先要保证settings中的INSTALLED_APPS中有django.contrib.staticfiles。当settings中的DEBUG=True时,django会自动的处理。这种方法效率比较低,且不安全,只有在开发中才使用。而我们在生产环境中DEBUG一般是False。
-
settings中定义静态文件的URL:STATIC_URL = ‘/static/’
-
也可以设定额外的静态文件夹,django会自动的搜索
STATICFILES_DIRS = [ BASE_DIR / "static", '/var/www/static/', ]
-
还需要在settings中配置STATIC_ROOT,这里需要是绝对的路径,如
STATIC_ROOT='/home/Django/static'
当然更好是进行这样的设定,利用base路径,更灵活:
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
或者
STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), ‘static’)
-
进行静态文件的收集,这一步必须操作,因为我们用的python库,它会有js等静态文件,这会将库用的一些js静态文件迁移到这里。
python3 manage.py collectstatic
-
另外最好给static文件夹提升权限:
sudo chmod 777 static
静态文件配置完成。而媒体文件配置比较简单,我们在settings中加入:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
保险点的,我们可以在settings同级的urls.py中url列表,加入:
#媒体文件夹
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),
因为,我们后面会用Nginx直接访问媒体文件,所以我认为这个url配置是多余的。但是没有尝试,去掉后,媒体文件访问是否正常。
官网的参考:
- https://docs.djangoproject.com/en/3.1/howto/static-files/
- 生产中,静态文件的配置:
https://docs.djangoproject.com/en/3.1/howto/static-files/deployment/
django生产环境搭建原理###
配置django的生产环境就是利用nginx+uwsgi+django.而实现Nginx与uWSGI的连接,两者之间将采用soket来通讯方式
名词
https://www.cnblogs.com/gaosai/p/10319605.html
-
nginx:Web服务器和作为反向代理服务器:用来做负载均衡。比如静态文件处理,安全,效率等等。
正向代理:
我访问不了某网站比如www.google.com,但是我能访问一个代理服务器,这个代理服务器呢,它能访问那个我不能访问的网站,于是我先连上代理服务器,告诉它我需要那个无法访问网站的内容,代理服务器去取回来,然后返回给我。
反向代理当我们请求 www.baidu.com 的时候,当我们访问www.baidu.com的时候,背后可能有成千上万台服务器为我们服务,但具体是哪一台,不知道,也不需要知道,只需要知道反向代理服务器是谁就好了,www.baidu.com 就是我们的反向代理服务器,反向代理服务器会帮我们把请求转发到真实的服务器那里去。
-
WSGI:Web Server Gateway Interface,就是一个网关,用来在协议之间进行转换。比如作为nginx和uWSGI的通讯协议。在python实际的生产环境中,WSGI经常被使用。WSGI没有官方的实现, 因为WSGI更像一个协议,只要遵照这些协议,WSGI应用(Application)都可以在任何服务器(Server)上运行。
-
uWSGI:应用服务器:它实现了 WSGI 协议、uwsgi、http 等协议。Nginx 中HttpUwsgiModule 的作用是与 uWSGI 服务器进行交换。Nginx 中HttpUwsgiModule 的作用是与 uWSGI 服务器进行交换。
上文所述的uWSGI 实现了WSGI的所有接口,是一个快速、自我修复、开发人员和系统管理员友好的服务器。把 HTTP 协议转化成语言支持的网络协议。uWSGI代码完全用C编写,效率高、性能稳定。
- uwsgi(全小写): 和uWSGI 不一样,uwsgi是一种线路协议,不是通信协议,常用于在uWSGI服务器与其他网络服务器的数据通信。uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型。
注意 WSGI / uwsgi / uWSGI 这三个概念的区分:WSGI 是一种通信协议。uwsgi 是一种线路协议而不是通信协议,在此常用于在 uWSGI 服务器与其他网络服务器的数据通uWSGI 是实现了 uwsgi 和 WSGI 两种协议的 Web 服务器。
参考:https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
配置django的生产环境就是利用nginx+uwsgi+django.而实现Nginx与uWSGI的连接,两者之间将采用soket来通讯方式
django生产环境的访问流程
-
首先浏览器发起 http 请求到 nginx 服务器,Nginx 根据接收到请求包,进行 url 分析,判断访问的资源类型,
-
如果是静态资源,直接读取静态资源返回给浏览器,如果请求的是动态资源就转交给 uwsgi服务器,
-
uwsgi 服务器根据自身的 uwsgi 和 WSGI 协议,找到对应的 Django 框架,Django 框架下的应用进行逻辑处理后,将返回值发送到 uwsgi 服务器,
-
然后 uwsgi 服务器再返回给 nginx,最后 nginx将返回值返回给浏览器进行渲染显示给用户。
uwsgi的官方说明:https://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html
服务器架构:
django的uwsgi和nginx的配置
知道了原理后,我们进行uwsgi和nginx配置,才会明白每一项的含义。
uwsgi的配置
参考:https://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html
简单熟悉uwsgi的用法和作用
我们先建立一个简单的python应用foobar.py:
#定义应用的意思是这是uWSGI的默认的python加载器,uWGSI能够自动搜索到
def application(env, start_response):
start_response(‘200 OK’, [(‘Content-Type’,‘text/html’)])
return [b"Hello World"]
然后我们使用以下命令:
uwsgi --http :9090 --wsgi-file foobar.py
然后我们可以给其增加进程和线程:
uwsgi --http :9090 --wsgi-file foobar.py --master --processes 4 --threads 2
当然我们也可以挂载django项目,假设django项目在/home/foobar/myproject:
uwsgi --socket 127.0.0.1:3031 --chdir /home/foobar/myproject/ --wsgi-file myproject/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
从上面可以看到命令太长,当然了我们可以设定一个配置文件,来启动django项目,所以这就是uWGSI配置文件,以及我们需要配置文件.ini
的原因了,上面的可以配置uswgifile.ini
一般与与manage.py在同一级目录:
[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
wsgi-file = myproject/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:9191
然后,就可以直接运行: uwsgi yourfile.ini
可以看到,上面有一个wsgi-file文件,这个django1.4以后的版本,在创建项目的时候都会自动生成,在跟settings.py同级的文件下,如上面的项目是在/home/foobar/myproject/myproject/wsgi.py。如果没有这个wsgi.py,可以配置如下:
[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
pythonpath = ..
env = DJANGO_SETTINGS_MODULE=myproject.settings
module = django.core.handlers.wsgi:WSGIHandler()
processes = 4
threads = 2
stats = 127.0.0.1:9191
django生产环境的uwsgi配置示例
从上面的例子,我们知道,uwsgi无非就是写个配置文件,启动就行,一般生产环境用的uwsgi如下:
[uwsgi]
# Django-related settings
# the base directory (full path)
chdir = /home/Django/
# Django's wsgi file,django2.0会自动生成一wsgi文件,在settings统计的目录下
module = Django.wsgi
# the virtualenv (full path)
home = /home/IHIT/Django/venv
#如果找不到django等模块的错误,可以尝试加这个参数
#pythonpath=/home/Django/venv/lib/python3.6/site-packages
# process-related settings
# master
master = true#以主近程模式运行
# maximum number of worker processes,一般为cpu的核心数
processes = 4
#两个线程
threads=2
# 存放进程编号的文件,这个pid文件可以用来快速的停止uwsgi。
pidfile= /home/IHIT/Django/uwsgi.pid
# the socket (use the full path to be safe,这个是套接字文件,表示Unix套接字.在这种情况下,uWSGI会创建它,并且将通过此套接字uWSGI和Nginx将彼此通信.)
socket = /home/IHIT/Django/mysite.sock
# ... with appropriate permissions - may be needed,这个是权限设置,如果把permission error 13,就需要加上这个权限设置,666这个权限的意思跟linux文件夹的权限是一样的。
chmod-socket = 666
# clear environment on exit
vacuum = true
# 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的
daemonize=/home/IHIT/Django/logs/uwsgi/uwsgi.log
# 仅记录错误信息,减少日志文件的体积
disable-logging = true
uswgi的参数配置很多,我们可以参考下面的说明:
uwsgi基础使用命令:启动。停止,重启
-
启动:
uwsgi --ini xxx.ini
-
重启:
uwsgi --reload xxx.pid
-
停止:
uwsgi --stop xxx.pid
如果不知道pid号,可以是用 ps aux |grep uwsgi查看,然后进行kill
配置uwgsi遇见的问题:####
-
配置uwgsi时,出现找不到django模块的错误:如
Traceback (most recent call last): File "./Django/wsgi.py", line 12, in <module> from django.core.wsgi import get_wsgi_application ModuleNotFoundError: No module named 'django' unable to load app 0 (mountpoint='') (callable not found or import error) *** no app loaded. going in full dynamic mode ***
这个问题一般是没有配置好python虚拟环境在的位置,重新配置home参量所对的python虚拟环境的路径。如果还不行,在uwgsi中,可以用以下的命令看看django在哪个位置:
pip show django|grep -i location
结果是一个路径:
Location: /usr/local/lib64/python3.6/site-packages
把这个路径加在uwgsi文件中:
pythonpath=/usr/local/lib64/python3.6/site-packages
配置nginx
nginx的简单说明####
与uwsgi一样的, nginx也是写好配置文件,运行即可。
为了实现Nginx与uWSGI的连接,两者之间将采用soket来通讯方式(上文介绍过).Nginx一般采用8077端口与uWSGI通讯.一般可以通过端口进行通信,如在nginx配置文件中有:
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:3031;
}
注:这个location其实就相当于你在开发django时的url。 如果明白这个,那对nginx的反向代理应该就能理解了。(理解这个,我们我们也就能对同一域名不同的url设置不同的后台。,或者对不同的域名指定不同后台等多站配置操作)
然后uswgi可以这么配置协议:
uwsgi --socket 127.0.0.1:3031 --wsgi-file foobar.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
这说明了服务器的每一个请求都通过3031端口送给uwsgi
配置nginx.conf
-
首先我们需要一个nginx的参数文件:
uwsgi_params
file。这个文件要配置到我们的项目的目录下,这一步很容易被忽略! -
在**/etc/nginx/sites-available/ **目录下创建一个配置文件:mynginx.conf ,也可以修改default的
配置文件示例如下,这里配置了两个django项目,一个通过TCP套接字,一个是unix套接字:
# the upstream component nginx needs to connect to #这里主要是做负载均衡的,也是nginx和uwsgi连接的地址 upstream django { #django项目的端口号 和uwsgi里面的端口号保存一制 server 127.0.0.1:8000; # for a web port socket (we'll use this first)#这里是tcp套接字 } # configuration of the server server {#第一个域名配置 # nginx服务的端口号 不用修改,HTTP访问通过80端口, listen 80; # the domain name it will serve for # 这里可以填写你的ip地址或者域名,多个域名中间空格隔开 server_name www.XXX.show; charset utf-8; gzip on; gzip_disable "msie6"; gzip_proxied any; gzip_min_length 1k; gzip_comp_level 4; gzip_types text/plain text/css application/json application/x-javascript text/javascript text/xml image/jpeg image/png image/gif; # max upload size client_max_body_size 75M; # adjust to taste access_log /home/loverweb/website/logs/nginx/host.access.log; # 日志文件 error_log /home/loverweb/website/logs/nginx/error.log; # 日志文件 # Django media location /media { alias /home/loverweb/media; # 指向django的media目录 } location /static { alias /home/loverweb/static_all; # 指向django的static目录 } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass 127.0.0.1:8000;#nginx与uwsgi通信的接口,这里是TCP端口套接字,还能用unix 套接字 include uwsgi_params; # the uwsgi_params file you installed } } #第二个django配置 upstream IHT { #UNIX套接字,一般是使用这个sock文件,这个文件,uwsgi中也配置了,是一样的 server unix:///home/IHT/Django/mysite.sock; } server {#第二个域名配置 # nginx服务的端口号 不用修改,https使用的443端口 listen 443; # the domain name it will serve for # 这里可以填写你的ip地址或者名,可以配置多个,空格打开就行 server_name www.XXX.fun; #https的ssl证书配置,阿里云可以申请免费的ssl证书, ssl on; ssl_certificate /home/IHT/Django/ssl/www.XXX.fun.pem; ssl_certificate_key /home/IHT/Django/ssl/www.XXX.fun.key; ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; charset utf-8; gzip on; gzip_disable "msie6"; gzip_proxied any; gzip_min_length 1k; gzip_comp_level 4; gzip_types text/plain text/css application/json application/x-javascript text/javascript text/xml image/jpeg image/png image/gif; # max upload size client_max_body_size 75M; # adjust to taste access_log /home/IHT/Django/logs/nginx/host.access.log; #日志 error_log /home/IHT/Django/logs/nginx/error.log; # # Django media location /media/ { alias /home/IHT/Django/media/; # 指向django的media目录 } location /static/ { alias /home/IHT/Django/static/; # 指向django的static目录 } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass IHT;#nginx和uwsgi连接,注意这个IHT是upstream IHT的名字 include /home/IHT/Django/uwsgi_params; # the uwsgi_params file you installed } }
-
将nginx配置文件链接到sites-available文件夹中,就可以启动nginx了(
systemctl start nginx.service
)。当sites-available有这个文件时,我们需要把它删掉再进行运行sudo ln -s /etc/nginx/sites-available/mynginx.conf /etc/nginx/sites-enabled/
若nginx运行时,提示用户的权限不够,把user = nginx改成user = root即可
配置参考
多域名的nginx配置参考:
- [https://ruanjianlaowang.blog.csdn.net/article/details/93588247?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight](https://ruanjianlaowang.blog.csdn.net/article/details/93588247?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.edu_weight)
- [https://blog.csdn.net/nightelve/article/details/19265421?utm_source=app](https://blog.csdn.net/nightelve/article/details/19265421?utm_source=app)
nginx的命令
-
启动服务:
systemctl start nginx.service
-
开机启动
systemctl enable nginx
-
重启服务
systemctl restart nginx.service
-
重载配置文件:
nginx -s reload
-
查看端口号
nginx -s reload
-
查看进程:
ps -ef|grep nginx ps aux |grep nginx
-
查看是否监听
ss -tnl | grep 80
-
查看nginx 启动状态
systemctl status nginx
-
停止服务
建议:
systemctl stop nginx.service
停止的四种命令
从容停止服务
这种方法较stop相比就比较温和一些了,需要进程完成当前工作后再停止。nginx -s quit
立即停止服务
这种方法比较强硬,无论进程是否在工作,都直接停止进程。nginx -s stop
systemctl 停止
systemctl属于Linux命令systemctl stop nginx.service
killall 方法杀死进程
直接杀死进程,在上面无效的情况下使用,态度强硬,简单粗暴!killall nginx
参考:
[https://blog.csdn.net/weixin_30632899/article/details/99771835?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight](https://blog.csdn.net/weixin_30632899/article/details/99771835?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight)
nginx使用错误
-这个错误一般是配置文件出错了,不能进行启动
nginx.serviceJob for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
在nginx的目录下运行:
nginx -t
查看nginx配置文件的错误的地方,然后进行修改即可
django部署配置时,常见的502 Gateway
这个错误查看nginx,发现一般错误如下:
connect() to unix:///path/to/your/mysite/mysite.sock failed (13: Permission denied)
这个问题官网有提到,需要提升权限,
- 最高权限:–chmod-socket=666
- 稍低的权限: --chmod-socket=664
配置https访问
-
方法1
如果要配置https访问,需要配置SSL证书,一般在云服务器商申请即可,然后进行签发,下载nginx格式的,有.pem和.key两个文件。
腾讯云可以按照这个思路进行申请:https://jingyan.baidu.com/article/d45ad1487ff97669542b8074.html
申请到证书,上传到服务器,就修改nginx的配置,监听433端口,并且,配置ssl如下:
server { # nginx服务的端口号 不用修改,https配置 listen 443; # the domain name it will serve for # 这里可以填写你的ip地址或者名,可以配置多个,空格打开就行 server_name www.XXX.fun; #https的ssl证书配置 ssl on; ssl_certificate /home/Django/ssl/XXX.pem;#pem文件所在的目录 ssl_session_timeout 5m; ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ... }
-
方法2:
参考:https://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html
上面的文档在Security and availability节提到了,以下配置https:
[uwsgi]
shared-socket = :443
https = =0,foobar.crt,foobar.key
uid = foo
gid = bar
chdir = path_to_web2py
module = wsgihandler
master = true
processes = 8
不过这个需要自己手动签发一个ssl文件,利用openssl程序即可完成。
这个方法没有测试过