Django3.0.8生产环境部署nginx、uwsgi、daphne、supervisor、gunicorn、celery

本文主要是介绍Django3.0.8生产环境部署nginx、uwsgi、daphne、supervisor、gunicorn、celery,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 前言
  • 环境配置
  • 技术方法
  • 实现过程
    • 安装Python3.8.3
    • 安装Nginx
    • 安装MySQL
    • 安装Redis
    • 安装虚拟环境 virtualenv
    • 创建虚拟环境
      • python中的virtualenv命令集
    • 在虚拟环境中安装pip包
    • 将项目文件上传到服务器规划的目录
    • 拉取所有需要的static file到同一目录
    • 配置nginx作为反向代理服务器
    • 编辑uwsgi文件
    • 使用supervisor管理daphne和uwsgi进程
    • 使用gunicorn + gevent替代uwsgi, 并发性能会好一点
    • 使用logrotate + crontabs切割日志
    • settings.py 中LOGGING的配置
    • 最后
  • 部署中遇到的错误和解决办法
      • 1. 启动supervisor时报错:
      • 2. Nginx Permission Denie问题:
      • 3. Nginx启动时报错:
      • 4. MySQL报错
        • 原因分析:
        • 解决方案

前言

因为项目中用到了channels做websocket消息推送,所以以前那种nginx+uwsgi的模式行不通了~,channels推荐的是daphne服务器,所以Google了一下,都说是用nginx+uwsgi+daphne+supervisor这一套组合来部署。看了下网上的教程,七零八落的,好不容易才拼凑起来,所以才有自己总结一下的想法。

环境配置

服务器:CentOS8.2 64位
开发平台: Python3.8.3
Web框架: Django3.0.8
数据库: MySQL 8.0
缓存数据库: Redis

技术方法

使用Nginx代理,将http部分请求发送给uwsgi或者gunicorn进行处理,将websocket部分请求发送给daphne进行处理。uwsgi和daphhe均使用supervisord进行控制。
需要注意的是,由于Nginx无法识别http请求和websocket请求,需要通过路由来区分是哪种协议。我使用的方法是规定所有的websocket的路由均以/ws开头(如: ws://www.example/ws/table/table_id/),这样就可以让Nginx将所有以/ws开头的请求全部转发给daphne进行处理。
当然,这一切都是在服务器的一个虚拟环境中。

实现过程

安装Python3.8.3

安装方法在我另一篇博客中: 如何在 CentOS 8 上安装 Python 3.8
如果嫌pip安装太慢,可以参考这篇文章:更换pip源到国内镜像

安装Nginx

  1. 安装 Nginx
yum install nginx -y
  1. 启动软件并设置开机启动
systemctl enable nginx
systemctl start nginx
  1. 查看命令行检测安装完成。
[root@www.mf8.biz ~]# nginx -V
nginx version: nginx/1.14.1
built by gcc 8.2.1 20180905 (Red Hat 8.2.1-3) (GCC) 
built with OpenSSL 1.1.1 FIPS  11 Sep 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/run/nginx.pid --lock-path=/run/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -Wl,-E'
  1. 设置防火墙规则
firewall-cmd --permanent --zone=public --add-service=http 
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload
  1. 访问IP即可

在这里插入图片描述

配置文件目录

主配置文件:/etc/nginx/nginx.conf默认文件目录:/usr/share/nginx/html错误日志:/var/log/nginx/error.log访问日志:/var/log/nginx/access.log

安装MySQL

参考我的这篇文章: CentOS 8 安装MySQL 8.0

安装Redis

参考我的这篇文章:CentOS 8安装Redis的两种方式

安装虚拟环境 virtualenv

pip install virtualenvwrapper

接下来编辑.bashrc文件,这是重点

[root@ITCMDB ~]# vi ~/.bashrc添加下面j几行
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python  # 指定virtualenvwrapper执行的python版本
export WORKON_HOME=$HOME/.virtualenvs  # 指定虚拟环境存放目录,.virtualenvs目录名可自拟
VIRTUALENVWRAPPER_VIRTUALENV_ARGS='' # 添加virtualenvwrapper的参数,生成干净隔绝的环境source /usr/local/bin/virtualenvwrapper.sh  # virtualenvwrapper.sh所在目录

保存后,重载./bashrc文件

source ~/.bashrc

创建虚拟环境

执行命令

mkvirtualenv kzitcmdb(虚拟环境名称)

就创建好了, 当然,还有许多命令选项,我这里就不多说了

python中的virtualenv命令集

irtualenv

# 安装
$ pip install virtualenv
# 激活虚拟环境
$ source my_project/bin/activate
# 退出虚拟环境
$ deactivate
# 输出当前依赖包
$ pip freeze > requirements.txt
# 安装依赖包
$ pip install -r requirements.txt

virtualenvwrapper

# 安装
$ pip install virtualenvwrapper
# 修改~/.zshrc
$ cat ~/.zshrc
if [ -f /usr/local/bin/virtualenvwrapper.sh ]; thenexport WORKON_HOME=$HOME/virtualenvssource /usr/local/bin/virtualenvwrapper.sh
fi
# 创建虚拟环境,创建成功后 $WORKON_HOME 下会多出一个文件夹
$ mkvirtualenv my_prj
# 使用虚拟环境
$ workon my_prj
# 退出虚拟环境
$ deactivate
# 删除
$ rmvirtualenv my_prj
# 列出所有环境
$ lsvirtualenv
# 进入到当前虚拟环境中
$ cdvirtualenv
# 进入到当前虚拟环境的 site-packages 中
$ cdsitepackages

.gitignore

*.py[cod]     # 将匹配 .pyc、.pyo 和 .pyd文件
__pycache__/  # 排除整个文件夹

在虚拟环境中安装pip包

将准备的requirements.txt上传到服务器
然后执行下面命令

[root@ITCMDB /]# workon led_dev
(led_dev) [root@ITCMDB /]# pip install -r requirements.txt

等待安装完成即可

将项目文件上传到服务器规划的目录

/root/webapp

同时,将数据库上传到服务器
本例中,用navicat进行数据库的复制。
此时,可以通过python内置的服务器进行测试

(kzitcmdb) [root@ITCMDB wwwroot]# python manage.py runserver 0.0.0.0:9999

启动成功后,在浏览器进行测试。

拉取所有需要的static file到同一目录

在django的setting文件中,添加下面一行内容:

STATIC_URL = '/static/'STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"),
]

并在项目根目录下运行命令:

 python manage.py collectstatic

完成后,重启nginx

配置nginx作为反向代理服务器

我这里是把我的项目的nginx配置文件放在了项目文件夹中,便于管理
在这个目录下新建一个led.conf

[root@ITCMDB nginx]# pwd/root/webapp/LED/conf/nginx/

编辑led.conf

upstream led {server unix:///root/webapp/LED/conf/sock/server.sock fail_timeout=0;
}upstream websocket {server unix:///root/webapp/LED/conf/sock/websocket.sock fail_timeout=0;
}log_format  access_exp  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';server {listen 8000;server_name 192.168.12.156; # substitute your machine's IP address or FQDNcharset utf-8;client_max_body_size 1024M;location /media {alias /root/webapp/LED/media/;}location /static {alias /root/webapp/LED/static/;}access_log /root/webapp/LED/log/nginx/access.log access_exp;error_log /root/webapp/LED/log/nginx/error.log;open_log_file_cache max=10;location / {# gunicorn 配置# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# proxy_set_header Host $http_host;# proxy_redirect off;# if (!-f $request_filename) {# proxy_pass http://led;# break;#}# uwsgi 配置uwsgi_pass led;include /root/webapp/LED/conf/uwsgi/uwsgi_params;}location /ftp {alias  /root/webapp/LED/media/file/;   #目录文件服务器根目录autoindex on;   #允许nginx在浏览器以文件夹形式访问autoindex_exact_size off;  #显示文件大小autoindex_localtime on;    #显示文件时间charset utf-8; # 避免中文乱码}location /push {proxy_pass http://websocket;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_redirect     off;proxy_set_header   Host $host;proxy_set_header   X-Real-IP $remote_addr;proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header   X-Forwarded-Host $server_name;proxy_read_timeout  36000s;proxy_send_timeout  36000s;}
}

然后需要将led.conf软链接到/etc/nginx/conf.d/文件夹下,这样nginx才能加载到你的配置文件

ln -s /root/webapp/LED/conf/nginx/led.conf /etc/nginx/conf.d/

在Nginx和daphne以及uwsgi进行通信时,有http socket和file socket两种通信方式,推荐使用后一种file socket的方式, 也就是我用的这种。

编辑uwsgi文件

我这里是把我的项目uwsgi的ini文件也放在了项目文件夹中,便于管理
在这个目录下新建一个led.ini

[root@ITCMDB uwsgi]# pwd/root/webapp/LED/conf/uwsgi/

编辑led.ini

[uwsgi]
#使用nginx连接时使用
socket=/root/webapp/LED/conf/sock/server.sock#直接做web服务器使用 python manage.py runserver ip:port
#http=0.0.0.0:8000#项目目录
chdir=/root/webapp/LED#项目中wsgi.py文件的目录,相对于项目目录
wsgi-file=LED/wsgi.py#指定启动的工作进程数
processes=2#指定工作进程中的线程数
threads=2#指定在这些进程里有一个主进程
master=True#保存启动之后主进程的pid
pidfile=/root/webapp/LED/conf/uwsgi/uwsgi.pid#设置uwsgi后台运行,uwsgi.log保存日志信息
daemonize=/root/webapp/LED/log/uwsgi.log#设置日志文件最大字节数
log-maxsize = 100000#设置每个进程最大请求数
max-requests = 1000#设置虚拟环境的路径
virtualenv=/root/.virtualenvs/led_dev

重点:nginx的配置文件中有一个uwsgi_params文件,在/etc/nginx/文件夹内,拷贝到这个文件夹

使用supervisor管理daphne和uwsgi进程

安装教程:CentOS安装Supervisor

使用教程: supervised使用教程

我的daphne和uwsgi都是用supervisor管理的

编辑/etc/supervisord.conf 解除注释并修改(文件末尾)

[include]
files = /root/webapp/LED/conf/supervisor/*.conf

在/root/webapp/LED/conf/supervisor/文件夹新建 daphne.conf、uwsgi.conf、celery_worker.conf文件,因为我还用了celery,所以多一个celery的配置。

daphne.conf

[program:led.daphne]
command=/root/.virtualenvs/led_dev/bin/daphne -u /root/webapp/LED/conf/sock/websocket.sock LED.asgi:application
directory=/root/webapp/LED
user=root
autostart=true                ; 随着supervisord的启动而启动
autorestart=true              ; 自动重启。。当然要选上了
startretries=10               ; 启动失败时的最多重试次数
exitcodes=0                   ; 正常退出代码
stopsignal=KILL               ; 用来杀死进程的信号
stopwaitsecs=10               ; 发送SIGKILL前的等待时间
redirect_stderr=true          ; 重定向stderr到stdout
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=20
redirect_stderr=true
stdout_logfile=/root/webapp/LED/log/supervisor/daphne.log
; 给每个进程命名,便于管理
process_name=daphne_led
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
stopasgroup=true             ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
killasgroup=true             ; SIGKILL the UNIX process group (def false)

uwsgi.conf

;[program:led.uwsgi]
;command=/root/.virtualenvs/led_dev/bin/uwsgi --ini /root/webapp/LED/conf/uwsgi/led.ini
;directory=/root/webapp/LED
;user=root
;autostart=true                ; 随着supervisord的启动而启动
;autorestart=true              ; 自动重启。。当然要选上了
;startretries=10               ; 启动失败时的最多重试次数
;exitcodes=0                   ; 正常退出代码
;stopsignal=KILL               ; 用来杀死进程的信号
;stopwaitsecs=10               ; 发送SIGKILL前的等待时间
;redirect_stderr=true          ; 重定向stderr到stdout
;stdout_logfile_maxbytes=20MB
;stdout_logfile_backups=20
;stdout_logfile=/root/webapp/LED/log/supervisor/uwsgi.log
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
;stopasgroup=true             ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
;killasgroup=true             ; SIGKILL the UNIX process group (def false)

celery_worker.conf

[program:led.celery.worker]
command=/root/.virtualenvs/led_dev/bin/celery -A LED worker -B -l info  ; 被监控的进程路径
directory=/root/webapp/LED
user=root
numprocs=1
autostart=true                ; 随着supervisord的启动而启动
autorestart=true              ; 自动重启。。当然要选上了
startretries=3               ; 启动失败时的最多重试次数
exitcodes=0                   ; 正常退出代码
stopsignal=KILL               ; 用来杀死进程的信号
stopwaitsecs=10               ; 发送SIGKILL前的等待时间
redirect_stderr=true          ; 重定向stderr到stdout
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=20
stdout_logfile=/root/webapp/LED/log/supervisor/celery.log
; 给每个进程命名,便于管理
process_name=celery_led
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
stopasgroup=true             ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
killasgroup=true             ; SIGKILL the UNIX process group (def false)

启动supervisor

supervisord -c /etc/supervisord.conf

使用gunicorn + gevent替代uwsgi, 并发性能会好一点

gunicorn使用教程:
python之gunicorn的配置
gunicorn 使用教程
gunicorn + nginx:通过套接字或代理服务器

  1. 安装gunicorn
pip install gunicorn
pip install gevent   # 因为我使用的是gevent方式启动gunicorn
  1. 配置gunicorn
    在/root/webapp/LED/conf/gunicorn/ 文件夹内新建gunicorn.conf.py
import multiprocessing
import os
import sysBASE_DIR = '/root/webapp/LED/'sys.path.append(BASE_DIR)LOG_DIR = os.path.join(BASE_DIR, 'log/gunicorn/')
if not os.path.exists(LOG_DIR):os.makedirs(LOG_DIR)# 监听地址和端口
# bind = "127.0.0.1:8001"# 使用套接字
bind = "unix:/root/webapp/LED/conf/sock/server.sock"# 以守护进程的形式后台运行
daemon = True# 服务器中在pending状态的最大连接数,即client处于waiting的数目。超过这个数目, client连接会得到一个error。
# 建议值64-2048。
backlog = 512# 超时
timeout = 30# 调试状态
debug = False# gunicorn要切换到的目的工作目录
chdir = BASE_DIR# 工作进程类型(默认的是 sync 模式,还包括 eventlet, gevent, or tornado, gthread, gaiohttp)
worker_class = 'gevent'# 工作进程数
workers = (multiprocessing.cpu_count()) + 1# 客户端最大同时连接数。只适用于eventlet, gevent工作方式。
worker_connections = ((multiprocessing.cpu_count()) + 1) * 1000# 指定每个工作进程开启的线程数
# threads = multiprocessing.cpu_count() * 2# 日志
# 日志级别,这个日志级别指的是错误日志的级别(debug、info、warning、error、critical),而访问日志的级别无法设置
loglevel = 'info'# 其每个选项的含义如下:
'''
h          remote address
l          '-'
u          currently '-', may be user name in future releases
t          date of the request
r          status line (e.g. ``GET / HTTP/1.1``)
s          status
b          response length or '-'
f          referer
a          user agent
T          request time in seconds
D          request time in microseconds
L          request time in decimal seconds
p          process ID
'''# 访问日志文件
accesslog = os.path.join(LOG_DIR, 'gunicorn.access.log')# 错误日志文件
errorlog = os.path.join(LOG_DIR, 'gunicorn.error.log')# pid 文件
pidfile = os.path.join(BASE_DIR, 'conf/gunicorn/led_gunicorn.pid')# 进程名
proc_name = 'led.pid'# 指定worker进程的运行用户名。
user = 'root'# 更多配置请执行:gunicorn -h 进行查看

在/root/webapp/LED/conf/supervisor/文件夹新建 gunicorn.conf,注意: gunicorn.conf 和 uwsgi.conf部署的时候二选一就行了。到时候可以把另一个注释掉。
gunicorn.conf

[program:led.gunicorn]
command=/root/.virtualenvs/led_dev/bin/gunicorn LED.wsgi:application -c /root/webapp/LED/conf/gunicorn/gunicorn.conf.py  --log-level=info
directory=/root/webapp/LED
user=root
autostart=true                ; 随着supervisord的启动而启动
autorestart=true              ; 自动重启。。当然要选上了
startretries=10               ; 启动失败时的最多重试次数
exitcodes=0                   ; 正常退出代码
stopsignal=KILL               ; 用来杀死进程的信号
stopwaitsecs=10               ; 发送SIGKILL前的等待时间
redirect_stderr=true          ; 重定向stderr到stdout
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=20
stdout_logfile=/root/webapp/LED/log/supervisor/gunicorn.log
; 给每个进程命名,便于管理
process_name=gunicorn_led
; 默认为 false,如果设置为 true,当进程收到 stop 信号时,会自动将该信号发给该进$
stopasgroup=true             ; send stop signal to the UNIX process
; 默认为 false,如果设置为 true,当进程收到 kill 信号时,会自动将该信号发给该进$
killasgroup=true             ; SIGKILL the UNIX process group (def false)

使用gunicorn的nginx配置:
led.conf

upstream led {server unix:///root/webapp/LED/conf/sock/server.sock fail_timeout=0;
}upstream websocket {server unix:///root/webapp/LED/conf/sock/websocket.sock fail_timeout=0;
}log_format  access_exp  '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';server {listen 8000;server_name 192.168.12.156; # substitute your machine's IP address or FQDNcharset utf-8;client_max_body_size 1024M;location /media {alias /root/webapp/LED/media/;}location /static {alias /root/webapp/LED/static/;}access_log /root/webapp/LED/log/nginx/access.log access_exp;error_log /root/webapp/LED/log/nginx/error.log;open_log_file_cache max=10;location / {# gunicorn 配置proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $http_host;proxy_redirect off;if (!-f $request_filename) {proxy_pass http://led;break;}# uwsgi 配置# uwsgi_pass led;# include /root/webapp/LED/conf/uwsgi/uwsgi_params;}location /ftp {alias  /root/webapp/LED/media/file/;   #目录文件服务器根目录autoindex on;   #允许nginx在浏览器以文件夹形式访问autoindex_exact_size off;  #显示文件大小autoindex_localtime on;    #显示文件时间charset utf-8; # 避免中文乱码}location /push {proxy_pass http://websocket;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";proxy_redirect     off;proxy_set_header   Host $host;proxy_set_header   X-Real-IP $remote_addr;proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header   X-Forwarded-Host $server_name;proxy_read_timeout  36000s;proxy_send_timeout  36000s;}
}

启动supervisor

supervisord -c /etc/supervisord.conf

启动nginx

systemctl start nginx.service

没报错的话就是可以了~

使用logrotate + crontabs切割日志

安装:

yum -y install logrotate crontabs

配置:

  1. 先配置logrotate
    gunicorn-log-rotate和nginx-log-rotate文件:
/root/webapp/LED/log/gunicorn/*.log {su root rootnocompressdailycopytruncatecreatenotifemptyrotate 7olddir /root/webapp/LED/log/gunicornmissingokdateextpostrotate[ -e /root/webapp/LED/conf/gunicorn/led_gunicorn.pid ] && kill -USR1 $(cat /root/webapp/LED/conf/gunicorn/led_gunicorn.pid)endscript
}
/root/webapp/LED/log/nginx/*.log {su root rootnocompressdailycopytruncatecreatenotifemptyrotate 7olddir /root/webapp/LED/log/nginxmissingokdateextpostrotate[ -e /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`endscript
}
  1. 配置crontabs, 每天0点定时切割日志
    运行:
sudo crontab  -e

然后编辑:

# rotate nginx log erery day0 0 * * * /usr/sbin/logrotate -f /root/webapp/LED/conf/logrotate/nginx-log-rotate0 0 * * * /usr/sbin/logrotate -f /root/webapp/LED/conf/logrotate/gunicorn-log-rotate

settings.py 中LOGGING的配置

LOGGING = {'version': 1,'disable_existing_loggers': False,'filters': {'require_debug_false': {'()': 'django.utils.log.RequireDebugFalse'},'skip_static_requests': {'()': 'django.utils.log.CallbackFilter','callback': skip_static_requests},},'formatters': {'verbose': {'format': '%(levelname)s %(asctime)s %(process)d %(thread)d %(name)s:%(lineno)s %(funcName)s() %(message)s'},'verbose_sql': {'format': '%(levelname)s %(asctime)s %(process)d %(thread)d %(name)s:%(lineno)s %(funcName)s() %(sql)s\n%(params)s\n%(duration)ss'},},'handlers': {'console': {'level': 'DEBUG','filters': ['skip_static_requests'],'class': 'logging.StreamHandler','formatter': 'verbose',},'console_error': {'level': 'ERROR','filters': ['skip_static_requests'],'class': 'logging.StreamHandler','formatter': 'verbose',},'console_sql': {'level': 'WARNING','filters': ['skip_static_requests'],'class': 'logging.StreamHandler','formatter': 'verbose_sql',},},'loggers': {'django': {'handlers': ['console'],'level': 'INFO','propagate': True,},'django.request': {'handlers': ['console_error'],'level': 'ERROR','propagate': False,},'django.db.backends': {'handlers': ['console_sql'],'level': 'WARNING','propagate': False,},'django.security': {'handlers': ['console_error'],'level': 'ERROR','propagate': False,},'daphne': {'handlers': ['console',],'level': 'INFO'},},
}
def skip_static_requests(record):if isinstance(record.args, dict):if record.args.get('path', None):if record.args.get('path').startswith('/static/'):return Falseif record.args.get('path').startswith('/media/'):return Falseif record.args.get('path').startswith('/captcha/image/'):return Falsereturn True

最后

按上面步骤一步步来的话,基本就可以部署成功了,记得部署之前要把项目的settings配置文件配置好。

部署中遇到的错误和解决办法

1. 启动supervisor时报错:

 Error: Another program is already listening on a port that one of our HTTP servers is configured to use. Shut this program down first before starting supervisord. 

解决办法:
运行命令

unlink /tmp/supervisor.sock

2. Nginx Permission Denie问题:

open() "/etc/nginx/conf.d/led.conf" failed (13: Permission denied) in /etc/nginx/nginx.conf

或者是nginx静态资源文件无法访问,403 forbidden错误:

解决方法:

  1. CentOS8 下 解决Nginx Permission Denied问题(推荐)
  2. 解决Nginx出现403 forbidden (13: Permission denied)报错的四种方法

3. Nginx启动时报错:

nginx: [error] invalid PID number "" in "/run/nginx.pid"

解决办法
需要先执行

nginx -c /etc/nginx/nginx.conf

nginx.conf文件的路径可以从nginx -t的返回中找到。

nginx -t
nginx -s reload

4. MySQL报错

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
原因分析:

我们在连接mysql的时候,如果host是localhost, 就会使用Unix Domain Socket来连接, MySql默认的sock文件路径是/tmp/mysql.sock, 一些mysql 安装方法 将 mysql .sock放在/var/lib/mysql .sock或者其他的什么地方,你可以通过修改/etc/my.cnf文件来修正它(8.0的配置文件好像是在/etc/my.cnf.d/mysql-server.cnf),打开文件,可以看到如下的东东:

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysql/mysqld.log
pid-file=/run/mysqld/mysqld.pid
解决方案

1. 修改HOST
打开settings.py文件,找到DATABASES的HOST字段。
有两种修改方案:

  • 把localhost改成127.0.0.1, 使用内网连接
  • 把localhost改成/var/lib/mysql/mysql.sock
DATABASES = {'default': {                                                                                                               'ENGINE': 'django.db.backends.mysql','NAME': 'xxx','USER': 'root','PASSWORD': 'passwd','HOST':'127.0.0.1', # 或者 `/tmp/mysql.sock`'PORT':'3306',}}

2. 修改mysql的sock文件路径

vi etc/my.cnf  # 或者 /etc/my.cnf.d/mysql-server.cnf

将sock路径变更为/var/lib/mysql/mysql.sock

socket = /tmp/mysql.sock

重启MySql服务。

Centos机器上

systemctl restart mysqld.service

在这里我用的是软链接的方式,因为我不想修改这些默认的配置,毕竟小白一个…

mysql.sock 一般不是在 /tmp/mysql.sock 就是在 /var/lib/mysql/mysql.sock 这里,没有的话就用

ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock

或者是

ln -s /tmp/mysql.sock /var/lib/mysql/mysql.sock

3. 数据库连接指定sock路径

DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'xxx','USER': 'root','PASSWORD': 'passwd','OPTIONS': {"unix_socket": "/tmp/mysql.sock",},}
}

这篇关于Django3.0.8生产环境部署nginx、uwsgi、daphne、supervisor、gunicorn、celery的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/552740

相关文章

Windows环境下安装达梦数据库的完整步骤

《Windows环境下安装达梦数据库的完整步骤》达梦数据库的安装大致分为Windows和Linux版本,本文将以dm8企业版Windows_64位环境为例,为大家介绍一下达梦数据库的具体安装步骤吧... 目录环境介绍1 下载解压安装包2 根据安装手册安装2.1 选择语言 时区2.2 安装向导2.3 接受协议

SpringBoot基于沙箱环境实现支付宝支付教程

《SpringBoot基于沙箱环境实现支付宝支付教程》本文介绍了如何使用支付宝沙箱环境进行开发测试,包括沙箱环境的介绍、准备步骤、在SpringBoot项目中结合支付宝沙箱进行支付接口的实现与测试... 目录一、支付宝沙箱环境介绍二、沙箱环境准备2.1 注册入驻支付宝开放平台2.2 配置沙箱环境2.3 沙箱

一文详解Nginx的强缓存和协商缓存

《一文详解Nginx的强缓存和协商缓存》这篇文章主要为大家详细介绍了Nginx中强缓存和协商缓存的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、强缓存(Strong Cache)1. 定义2. 响应头3. Nginx 配置示例4. 行为5. 适用场景二、协商缓存(协

Nginx实现高并发的项目实践

《Nginx实现高并发的项目实践》本文主要介绍了Nginx实现高并发的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用最新稳定版本的Nginx合理配置工作进程(workers)配置工作进程连接数(worker_co

Nginx中location实现多条件匹配的方法详解

《Nginx中location实现多条件匹配的方法详解》在Nginx中,location指令用于匹配请求的URI,虽然location本身是基于单一匹配规则的,但可以通过多种方式实现多个条件的匹配逻辑... 目录1. 概述2. 实现多条件匹配的方式2.1 使用多个 location 块2.2 使用正则表达式

Nginx配置系统服务&设置环境变量方式

《Nginx配置系统服务&设置环境变量方式》本文介绍了如何将Nginx配置为系统服务并设置环境变量,以便更方便地对Nginx进行操作,通过配置系统服务,可以使用系统命令来启动、停止或重新加载Nginx... 目录1.Nginx操作问题2.配置系统服android务3.设置环境变量总结1.Nginx操作问题

linux环境openssl、openssh升级流程

《linux环境openssl、openssh升级流程》该文章详细介绍了在Ubuntu22.04系统上升级OpenSSL和OpenSSH的方法,首先,升级OpenSSL的步骤包括下载最新版本、安装编译... 目录一.升级openssl1.官网下载最新版openssl2.安装编译环境3.下载后解压安装4.备份

如何使用Docker部署FTP和Nginx并通过HTTP访问FTP里的文件

《如何使用Docker部署FTP和Nginx并通过HTTP访问FTP里的文件》本文介绍了如何使用Docker部署FTP服务器和Nginx,并通过HTTP访问FTP中的文件,通过将FTP数据目录挂载到N... 目录docker部署FTP和Nginx并通过HTTP访问FTP里的文件1. 部署 FTP 服务器 (

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

Ubuntu 22.04 服务器安装部署(nginx+postgresql)

《Ubuntu22.04服务器安装部署(nginx+postgresql)》Ubuntu22.04LTS是迄今为止最好的Ubuntu版本之一,很多linux的应用服务器都是选择的这个版本... 目录是什么让 Ubuntu 22.04 LTS 变得安全?更新了安全包linux 内核改进一、部署环境二、安装系统