基于CentOS7下部署 Python3+Nginx+uWSGI+Django+Django REST Framework+MongoDB
分为以下几步:
- 服务器安装Nginx,本地浏览器能正常访问即可
- 服务器安装MongoDB,本地Navicate等数据库管理工具能远程连接到远程MongoDB
- 服务器搭建Python3环境
- 服务器搭建Django项目,接入DRF和MongoDB(也可本地编辑器搭建,然后通过ftp软件上传至服务器),并且本地浏览器能正常访问到,MongoDB正常持久化
- 接入uwsgi与第1步的Nginx,能本地通过Nginx正常访问到Django项目
安装Nginx
参考之前写过的文章:Nginx保姆式安装与入门使用 - 掘金 (juejin.cn)
安装MongoDB(version:4.2稳定版)
中文文档:MongoDB中文手册|官方文档中文版 - MongoDB-CN-Manual (mongoing.com)
安装
创建yum文件: vim /etc/yum.repos.d/mongodb-org-4.2.repo
写入下面内容
[mongodb-org-4.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.2/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc
执行:yum install -y mongodb-org
开启远程连接:
将配置文件bindIp: 127.0.0.1 修改为 bindIp: 0.0.0.0:vim /etc/mongod.conf
启动mongodb服务:service mongod start
设置开机自启动:
systemctl enable mongod
查看服务是否启动:systemctl status mongod
其他操作:
停止mongodb服务:service mongod stop
重启mongodb服务:service mongod restart
查看mongodb服务日志:cat /var/log/mongodb/mongod.log
本地navicate远程连接mongodb服务器
安全设置(需要可通过此设置密码验证)
创建root用户
- 输入mongo 进入mongodb环境
- 切换到admin :use admin
- 创建root用户:db.createUser({user: 'root', pwd: 'thy123', roles: ['root']})
- 完成后退出mongo:quit()
- 再次进入mongo环境, 选择admin库,查看是否可以登录:db.auth('root','xxxxxxxxxxx') 返回1就是登录成功。
给具体库添加用户,并且授予权限
(mongodb的逻辑是:库可以添加用户,并给予这个用户特定的权限,这样就可以以这个用户的身份进行权限内的使用)
example:给admin库添加一个用户root,并赋予所有权限
use admin
db.createUser({ user: 'admin', pwd: 'xxxxxxxxx', roles: [{ role: 'root', db: 'admin' }] })
这里的role: 'root' 意思是给这个用户的角色是root角色,对应这个admin库的所有权限。和我们上面说的root用户没任何关系
这里的权限包括:
Read:允许用户读取指定数据库
readWrite:允许用户读写指定数据库
dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户
clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限
userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。
root:只在admin数据库中可用。超级账号,超级权限
注意:这时,以上的安全设置到目前为止还没有生效,需要到配置文件中开启安全认证。
开启安全认证
vi /etc/mongod.conf
找到“#security:”项,开启并在其下方添加:
security:
authorization: enabled
重启mongodb(没重启就不生效):service mongod restart
要建立其他的库,也相应地给他加上用户和权限
安装Python3环境(3.8.0)
一般习惯将软件安装包放在/usr/local/src下面,软件安装在/usr/local下。
踩坑:【3.6是PYTHON的谎言】千万别用python3.6.0和3.6.1_Reza.的博客-CSDN博客
解决:CentOS7 下升级Python版本 - Python - E度笔记 (edbiji.com)
在执行解决方法6.1之前,如果已经安装了python3.6并且没有覆盖掉python2,则先删除python3和pip3的软连接,然后根据解决方法里面的步骤执行。(注意,如果3.6安装了uwsgi并且创建了软连接,同样需要删除,不然依然用的pip3.6下载的uwsgi)
yum install zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel xz xz-devel libffi-devel
rm -rf /usr/bin/python3
rm -rf /usr/bin/pip3
rm -rf /usr/bin/uwsgi 根据安装的3.8 下载uwsgi然后重新创建软连接
并且之前下载的包也得重新下载pip3 install -r requirements.txt,因为现在是3.8,之前下的包在3.6里面
Shell脚本安装
root用户下 新建install_python3.sh
文件:vim install_python3.sh
,将下面的内容复制到文件中
#!/bin/bash
# 安装依赖包
yum -y groupinstall "Development tools"
yum -y install zlib-devel bzip2 bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz xz-devel libffi-devel
# 将软件包下载到/usr/local/src下
cd /usr/local/src
# 淘宝镜像下载python3.8.0版本
wget http://npm.taobao.org/mirrors/python/3.8.0/Python-3.8.0.tgz
# 解压
tar -xzf Python-3.8.0.tgz
# 进入解压包
cd Python-3.8.0
# 生成makefile文件,放在/usr/local/python3目录下
mkdir /usr/local/python3
./configure --prefix=/usr/local/python3
# 编译
make
# 安装
make install
# 创建软连接
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
给脚本授予权限:chmod 755 install_python3.sh
执行脚本安装:./install_python3.sh
通过python3 -V命令查看是否安装成功
正常安装
centos自带的有python2环境,一般下载其他版本会创建软连接而不会覆盖自带的python2环境,因为可能导致依赖python2的部分错误从而引发一些问题。
默认root用户,如果不是所有命令前加sudo
0.安装依赖包
yum -y groupinstall "Development tools"
yum -y install zlib-devel bzip2 bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz xz-devel libffi-devel
1.将软件包下载到/usr/local/src下,安装到/usr/local下。进入对应目录
cd /usr/local/src
2.官网速度可能比较慢,通过淘宝镜像下载python对应版本压缩包
官方下载:wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tar.xz
淘宝镜像下载(推荐):wget http://npm.taobao.org/mirrors/python/3.8.0/Python-3.8.0.tgz
3.解压淘宝镜像下载的文件 (解压后会出现一个 Python-3.8.0 文件夹):
tar -xzf Python-3.8.0.tgz
4.进入解压包:
cd Python-3.8.0
5.生成makefile文件,放在/usr/local/python3目录下:
mkdir /usr/local/python3
./configure --prefix=/usr/local/python3
6.编译:
make
7.安装:
make install
8.创建新版本python的软链接
(1) 利用命令 python3 调用新版本python,与自带的python不冲突
ln -s /usr/local/python3/bin/python3 /usr/bin/python3
(2) 利用命令 pip3 调用新版本pip,与自带的pip不冲突
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
此时系统中存在两个python版本:
命令 python 对应的仍是默认2.7版本, 命令 python3 则对应新安装的3.8版本
可以通过 python3 -V, pip3 -V查看下载的python和pip对应版本
服务器上部署Django+DRF
web项目代码习惯放在/home/web下面,将django项目放在/home/web/django目录下
安装Django
注意:Django4.0版本要求python版本最低为3.8
不过服务器上pip3 install Django的时候好像默认下载的是3.2版本
官网详情:FAQ:安装 | Django 文档 | Django (djangoproject.com)
-
创建虚拟环境(可跳过,直接安装在全局)
创建虚拟环境( /build是你生成的虚拟环境所在目录)
python3 -m venv /build/.virtualenvs/djangodev
进入该目录
cd /build
进入该虚拟环境
source /build/.virtualenvs/djangodev/bin/activate
-
通过pip下载安装Django
pip3 install Django
-
创建一个Django项目
创建/home/web/django目录:mkdir -p /home/web/django
进入到创建的目录:cd /home/web/django
初始化一个叫djangoProject的Django项目:django-admin startproject djangoProject
\注意:如果报错 django-admin:command not found,解决方法有两个:
(1) 创建软链接(推荐):先通过find命令找到django-admin执行位置find / -name django-admin
,根据找到的位置创建软链接:ln -s 找到的执行位置 /usr/bin/django-admin
如果按照我之前的步骤,应该执行的是ln -s /usr/local/python3/bin/django-admin /usr/bin/django-admin
(2) 用django-admin的绝对路径执行命令在当前目录下执行
django-admin startproject djangoProject
后,生成的目录结构如下:djangoProject ├── manage.py (启动整个django项目的入口) └── djangoProject (存放项目相关的文件) ├── __init__.py ├── settings.py (存放整个项目的配置信息) ├── urls.py (存放整个项目的url) ├── asgi.py () └── wsgi.py (用uwsgi时会用到)
-
运行demo
python3 manage.py runserver
命令默认是以127.0.0.1:8000运行
可以通过下面两种方式指明运行ip与port
python3 manage.py runserver 8080
(指明8080端口运行)
python3 manage.py runserver 0:8080
(0是0.0.0.0的缩写,可被本地浏览器访问)
执行python3 manage.py runserver 0:8080
后,通过本地浏览器输入服务器IP:8080访问后展示页面如下可能遇到的错误:
(1) django.core.exceptions.ImproperlyConfigured: SQLite 3.9.0 or later is required (found 3.7.17) 这是由于初始化的django项目默认用的sqlite数据库,报错是版本过低。
解决办法:
[1]更新sqlite版本: blog.csdn.net/weixin_5046…
[2]修改settings文件中DATABASES.default.ENGINE(推荐)( 注意:必须要设置default,即便ENGINE设为None):
方法一:DATABASES.default.ENGINE设置为None(推荐)方法二:修改settings文件中DATABASES.default.ENGINE为其他数据库
假设修改setting文件为'ENGINE': 'django.db.backends.mysql',并且配置了数据库相关信息 则pip3 install pymysql,然后在djangoProject/djangoProject/__init__.py中加入 import pymysql pymysql.install_as_MySQLdb() 再执行python manage.py migrate 然后执行python manage.py runserver可正常运行
(2) Invalid HTTP_HOST header: 'xxx.xxx.xxx.xxx:8000'. You may need to add 'xxx.xxx.xxx.xxx' to ALLOWED_HOSTS. 解决办法:据查阅,这是由于django防止HTTP主机头部攻击的措施导致,修改settings.py文件,将
ALLOWED_HOSTS = []
改为ALLOWED_HOSTS = ['*']
即可(亦或者添加相关ip和127.0.0.1)。再次运行即可成功访问。
Django接入DRF(django rest framwork)
- 安装:
pip3 install djangorestframework
- 在项目settings.py文件的 INSTALLED_APPS 中添加
'rest_framework'
INSTALLED_APPS = [ ... 'rest_framework', ]
- 如果打算使用可浏览的API,还需要添加REST框架的登录和注销视图。将以下内容添加到djangoProject/djangoProject/urls.py
from django.urls import include from rest_framework import routers router = routers.DefaultRouter() urlpatterns = [ ... path('api-auth/', include('rest_framework.urls')) #URL 路径可以是想要的任何路径 ]
启动django项目:python3 manage.py runserver 0:8000
本地浏览器正常访问页面
接入MongoDB
通过pymongo操作MongoDB\
-
下载pymongo:
pip3 install pymongo
-
在djangoProject/settings.py中的DATABSES中加入mongodb相关配置
-
然后在djangoProject/__init__.py中初始化mongodb连接
import pymongo from settings import DATABASES # 开启了密码验证用uri连接 # uri = "mongodb://%s:%s@%s:%d/%s?authMechanism=SCRAM-SHA-1" % (USERNAME,PASSWORD,HOST,PORT,DATABASE) # my_mongodb_client = pymongo.MongoClient(DATABASES['mongo']['URI']) # 无验证连接 my_mongodb_client = pymongo.MongoClient( host=DATABASES['mongo']['HOST'], port=DATABASES['mongo']['PORT'], )#连接django服务器 # 选择对应数据库,必须提前在mongodb创建该数据库,集合可以不用提前创建 mongodb_db = my_mongodb_client[DATABASES['mongo']['DATABASE']] post_data = { 'name': 'thy1', 'item': 'book1', 'qty': 18, } result = mongodb_db.get_collection('user').insert_one(post_data) print(mongodb_db.list_collection_names())
-
测试:
单独运行__init__.py文件,应该打印结果['user']
\
-
如果以项目运行,需要将djangoProject/__init__.py中的
from settings import DATABASES
改为from .settings import DATABASES
并且注释掉打印相关信息import pymongo from .settings import DATABASES # 开启了密码验证用uri连接 # uri = "mongodb://%s:%s@%s:%d/%s?authMechanism=SCRAM-SHA-1" % (USERNAME,PASSWORD,HOST,PORT,DATABASE) # my_mongodb_client = pymongo.MongoClient(DATABASES['mongo']['URI']) # 无验证连接 my_mongodb_client = pymongo.MongoClient( host=DATABASES['mongo']['HOST'], port=DATABASES['mongo']['PORT'], )#连接django服务器 # 选择对应数据库,必须提前在mongodb创建该数据库,集合可以不用提前创建 mongodb_db = my_mongodb_client[DATABASES['mongo']['DATABASE']] # 在其他文件中引用mongodb_db即可
接入uwsgi+Nginx
接入uwsgi
注意: 我在windows10环境下安装有问题,建议部署在Linux环境时再使用uwsgi
Django官网托管uwsgi地址:如何用 uWSGI 托管 Django | Django 文档 | Django (djangoproject.com)
uWSGI官网配置选项地址:uWSGI选项 — uWSGI 2.0 文档 (uwsgi-docs-zh.readthedocs.io)
-
vim编辑uwgsi.ini文件(执行
vim uwsgi.ini
命令编辑uwsgi.ini文件,将下面内容复制到文件中后,按ESC进入命令模式然后按ZZ保存退出)[uwsgi] # 项目根目录的绝对路径,在加载前切换到当前目录,指定运行目录 chdir=/home/web/django/djangoProject # 加载一个WSGI模块,这里加载djangoProject/wsgi.py找个模块 module=djangoProject.wsgi # http访问 http-socket=0.0.0.0:8000 # 设置socket的监听队列大小(默认100) listen=128 # 设置生成2个worker进程 workers=2 # 设置每个work进程的线程数 threads=4 # 启动主进程,来管理其他进程,其他的uwsgi进程都是这个master进程的子进程,kill此进程,相当于重启所有uwsgi进程 master=true # 允许用内嵌的语言启动线程(允许在app程序中产生一个子线程) 多线程需要,例如apscheduler enable-threads=true # 使进程在后台运行,并将日志打到指定文件 daemonize=%(chdir)/uwsgi.log # 指定pid文件 pidfile = %(chdir)/uwsgi.pid
查漏补缺:uwgsi中http、http-socket和socket区别
-
http: 自己会产生一个http进程(可以认为与nginx同一层)负责路由http请求给worker, http进程和worker之间使用的是uwsgi协议
-
http-socket: 不会产生http进程, 一般用于在前端webserver不支持uwsgi而仅支持http时使用, 他产生的worker使用的是http协议
-
如果前端webserver支持uwsgi, 则直接使用socket即可(tcp or unix)
因此,如果想直接将uwsgi用作服务器,例如像nginx那样直接暴露在公网那么就使用http; 如果有单独的服务器(例如nginx),由服务器将请求转发给uwsgi处理,并且使用http协议,那么此时使用http-socket。
http和http-socket对应的nginx配置: server{ listen 80; location / { proxy_pass http://127.0.0.1:5000/ // 必须用http:// } }
-
socket:按照uwsgi文档给出的解释是bind to the specified UNIX/TCP socket using default protocol.也就是说指定UNIX/TCP socket作为默认的协议。
UNIX/TCP socket其实是两类socket。UNIX socket是进程间的通信(Inter Process Communication),但只在同一台机器上;TCP/IP sockets允许进程通过网络通信。
在uwsgi中如果配置如下则是使用UNIX socket: [uwsgi] socket = /tmp/uwsgi.sock 如果配置如下则是使用TCP/IP socket: [uwsgi] socket = 127.0.0.1:8000 在nginx也是对应的配置(引): uWSGI socket(unix socket): location / { uwsgi_pass unix:///tmp/uwsgi.sock; include uwsgi_params; } TCP sockets: location / { uwsgi_pass 127.0.0.1:8000; include uwsgi_params; } 但是官方文档将两种形式写在一起了,没懂: [uwsgi] socket = /tmp/uwsgi.sock socket = 127.0.0.1:8000 workers = 3 master = true 注:uwsgi-socket是socket的别名引
-
-
安装uwsgi:
pip3 install uwsgi
-
启动uwsgi:
uwsgi uwsgi.ini
如果报错uwsgi: command not found...
解决方法:
(1)通过find命令找到uwsgi执行位置find / -name uwsgi
(2)创建软连接:ln -s 显示的路径 /usr/bin/uwsgi
(3)重新执行uwsgi uwsgi.ini
正常启动 或者uwsgi -version
正常显示版本信息即可
但是当用本地浏览器访问时会发现这样的页面,通过F12查看可知是静态文件请求不到(至少现在uwsgi+django是已经接通了)
下面通过Nginx解决这个问题。
接入Nginx
-
Django静态文件收集
(1) 编辑djangProject/settings.py文件,在BASE_DIR = Path(\_\_file\_\_).resolve().parent.parent
下面加入STATIC_ROOT = os.path.join(BASE_DIR, "static/")
,记得导入os包:import os
效果如下:
(2) 然后执行python3 manage.py collectstatic
,在/home/web/django/djangoProject下会多出一个static文件,里面包含了当前项目用到的所有静态文件 -
配置Nginx
(1) 修改nginx.conf配置文件
vim /usr/local/nginx/conf/nginx.conf
(2) 在http中添加include /usr/local/nginx/conf/conf.d/*.conf;
(3) 为当前django项目创建对应nginx配置文件
mkdir /usr/local/nginx/conf/conf.d
vim /usr/local/nginx/conf/conf.d/djangoProject.conf
,在文件中添加以下内容upstream django { # 本地8000端口 server 127.0.0.1:8000; # for a web port socket (we'll use this first) } server { # the port your site will be served on listen 8001; #以为django项目是8000端口,所以监听8001端口 # the domain name it will serve for server_name _; # 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 #} # 配置静态文件路径 location /static { alias /home/web/django/djangoProject/static; # your Django project's static files - amend as required } # Finally, send all non-media requests to the Django server. location / { proxy_pass http://django; #如果就一个,可以直接写proxy_pass http://IP:PORT; #uwsgi_pass django; #include /usr/local/nginx/conf/uwsgi_params; # the uwsgi_params file you installed } }
(4) 执行
nginx -s reload
重新加载nginx配置文件
(5) 通过本地浏览器访问 服务器IP:8001 即可正常显示(因为我使用的是nginx代理静态文件,所以8000端口访问的还是之前访问不到静态文件的样子)
(建议uwsgi不对公网开放,通过nginx代理打到本地8000端口,只需要修改uwgsi.ini文件 将0.0.0.0:8000改为127.0.0.1:8000)