网上关于nginx+uwsgi+django搭建的博客很多,但是我在按照前辈们的博客配置的过程中出现了或多或少的错误,所以这里记一篇笔记。主要是配置过程及配置之前需要考虑的一些问题,以及将一些常用的命令或者部分地方自己的理解集合在一片博客中,如果有不正确的地方,希望可以给予更正~~~
这一篇可能略微繁琐,若只需要配置的步骤,可以参考我的另一篇博客。
关于腾讯云初期使用的准备,建议参考腾讯云官方文档寻找自己的需求。
我这里主要参考了这两篇
管理 SSH 密钥
使用 SSH 登录 Linux 实例
注意,这个教程是windows系统的,mac系统上建议将密钥文件下载,并修改为没有后缀名,放到一个固定不轻易改动的文件夹中用已使用。
Mac直接在bash中输入**ssh root@你的主机ip ** (这里添加一篇如何登陆的教程)
Windows请下载ssh远程连接工具例如Putty
$ sudo ssh -i "path/to/密钥" [email protected]
在我们进行部署之前,最好可以保证我们的ubuntu是刚刚装好的,纯净的。可以选择通过命令“sudo su”切换到root用户,如果使用的是腾讯云的ubuntu用户,通过在之后的命令前添加sudo也可以。(以下命令默认添加)
Ubuntu18.04已经默认安装了python3.6,可使用python3命令查看
$ sudo apt install python3-pip
如果这里操作没有立即生效的话,可能需要重新登录服务器,并升级pip
$ pip3 install --upgrade pip
如果我们不使用python2做开发的话,这里建议删除python2的版本,或者设置python3为默认版本(也可以设置优先级) 参考:https://blog.csdn.net/OGirassol/article/details/103563616 ubuntu中同时存在python2和python3,如何将python3设置为默认版本
注:如果不修改的话,直接使用python3 manage.py runserver时可以正常启动,但是uwsgi时会报错:
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ImportError: No module named ‘encodings’
原因是因为用virtualenv创建虚拟目录时,默认版本为2.7,如果我们使用的python版本为3.x就会出错,而解决办法当然就是生成虚拟目录时指定python的脚本。当然这里可以在创建虚拟环境时指定python3的版本。
有时候在配置过程中需要关掉防火墙,或者开放某些端口,可通过以下命令关闭防火墙。
systemctl stop firewalld
systemctl status firewalld
systemctl disable firewalld
systemctl enable firewalld
我们使用sudo ufw enable命令来开发防火墙 通过sudo ufw status命令查看开启防火墙后的状态为active 说明防火墙开启成功。
接下来安装virtualenv和virtualenvwrapper:
$ pip3 install virtualenv
$ pip3 install virtualenvwrapper
#创建你项目的虚拟环境
$ mkvirtualenv django
# 创建虚拟环境的根目录
$ mkdir $HOME/.virtualenvs
#配置环境变量
$ sudo vim ~/.bashrc
将以下内容放到最后面
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export VIRTUALENVWRAPPER_VIRTUALENV=~/.local/bin/virtualenv
source ~/.local/bin/virtualenvwrapper.sh
激活环境变量来生效:
$ source ~/.bashrc
注:1:这里我在执行“ mkvirtualenv django”时出现了错误“mkvirtualenv: command not found”,原因是因为还没有修改环境变量,可以通过先执行之后的代码来完成。这里需要注意“source /.local/bin/virtualenvwrapper.sh”,有的博客教程中是“/usr/local/bin/virtualenvwrapper.sh”,而ubuntu18.04里,通过pip安装virtualenvwrapper得到的virtualenvwrapper.sh被安装在/.local/bin/目录下,所以如果路径错误的话需要更正。
2:修改环境变量的博客可以参考这篇:https://www.cnblogs.com/linga/p/11588223.html
3:之后的一切操作都需要在我们创建的django虚拟环境中运行,可以通过“$ workon django” 进入我们的虚拟环境
进行此操作前,请保证你现在已经处于Django这个虚拟环境中:
$ pip freeze > requirements.txt
$ pip install -r requirements.txt
通过第一个命令依赖库会导到于requirements.txt
通过第二个命令可以安装我们的依赖库。如果提醒权限不足,可以在前面添加sudo
这里大家可以安装自己需要的数据库,具体安装教程可以参考其他博客。
在安装了数据库之后,要对应的修改settings.py的内容。这里有一个问题,就是之前有一篇博客中说需要在settings.py中将“DEBUG = True”改为“DEBUG = False”,这里特别注意一下,不需要改!!!有的前辈的博客中说明的是为True,且经本人验证True可以运行而False不可以。(这里wsgi.py中选择了settings.py,所以如果您的项目可能不同阶段有不同的设置需求,可以通过自定义mysettings.py,并在wsgi.py中将其选择即可)
接下来我们可以通过使用FileZilla将django项目的代码上传至服务器,并测试运行了。
#进入虚拟环境
$ workon django
$ cd path/to/project
#同步到数据库
$ python manage.py migrate
$ python manage.py runserver 0.0.0.0:8000
在你的本机上输入服务器ip:8000测试能否访问,如果能访问则接着往下看(此时static静态资源还没有被代理加载不出来).
但是仅使用python自带的runserver工具运行网站程序,我们接下来安装nginx和uwsgi。
首先需要收集静态文件
#收集静态文件
$ python manage.py collectstatic
在settings.py中,注释掉STATICFILES_DIRS
#STATICFILES_DIRS=[
#os.path.join(BASE_DIR,'static')
#]
# 加入 STATIC_ROOT=os.path.join(BASE_DIR,'static')
settings.py中,debug改为True:
DEBUG = True
ALLOWED_HOSTS = ['*']
$ sudo apt-get install nginx
#查看是否运行
$ ps aux | grep nginx
如果已经在运行,可以看到nginx占用的端口、进程信息等。
安装完成后,在浏览器中输入你的ip地址,如果看到一个大标题是’Welcome to nginx!'的界面则说明安装完成!
这里粘贴出一些常用的命令:
/etc/init.d/nginx start #启动
/etc/init.d/nginx stop #关闭
/etc/init.d/nginx restart #重启
或者使用 sudo service nginx start/stop/restart
netstat -ap | grep 8000 #查看占用端口的情况
ps -ef | grep uwsgi
这里提醒一下,如果启动nginx服务的时候出现了错误:
Job for nginx.service failed because the control process exited with error code.
See “systemctl status nginx.service” and “journalctl -xe” for details.
可以通过这两个命令查看错误,一般可以在终端打印的结果中看到打印的错误,例如“nginx: configuration file /etc/nginx/nginx.conf test failed”可能就是因为配置文件中多写了分号或者配置项的某些值不正确等等,一般可以打印出来并对应更正。例如:
location / {
uwsgi_pass django;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
这里提一下第一条直接写django就可以,不需要写为ip:port的形式,第二条要写成uwsgi_params所在的路径,因为之前参考的博客直接写成了uwsgi_params,而未说明应该是其具体路径导致调试了好久,希望可以帮助到下一个配置的朋友。
这里如果在配置过程中出现了什么问题,可以卸载nginx重装后再进行配置。完全卸载nginx的代码如下:
$ sudo apt-get remove nginx nginx-common # 卸载删除除了配置文件以外的所有文件。
$ sudo apt-get purge nginx nginx-common # 卸载所有东东,包括删除配置文件。
$ sudo apt-get autoremove # 在上面命令结束后执行,主要是卸载删除Nginx的不再被使用的依赖包。
$ sudo apt-get remove nginx-full nginx-common #卸载删除两个主要的包。
安装uwsgi之前我们需要安装python开发包:
$ apt-get install python3.6-dev
然后再安装uwsgi,安装之前请先退出django这个虚拟环境,我们在公共环境中安装它.
$ pip3 install uwsgi
如果启动uwsgi出现no internal routing support, rebuild with pcre support,由于pip 可以强制下载重新编译安装的库,不然pip会直接从缓存中拿出了上次编译后的 uwsgi 文件,并没有重新编译一份,可以执行以下命令
$ sudo apt-get install libpcre3 libpcre3-dev
$ pip install uwsgi --no-cache-dir
安装完之后,我们首先测试uwsgi,在项目主目录下创建test.py文件:
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return [b"Hello World"]
在主目录下,通过uwsgi运行该文件:
$ uwsgi --http :8000 --wsgi-file test.py
由于这里指定的是8000端口,所以打开浏览器,输入xx.xxx.xxx.xx:8000/就可以看到“Hello World”了。
接下来配置Django与uwsgi连接,我们用uwsgi来测试网站是否能成功运行了,分别可以使用下面的命令:
$ uwsgi --http :8000 --file myweb/wsgi.py
$ uwsgi --http :8001 --module myweb.wsgi
$ uwsgi --http :8888 --chdir /home/ubuntu/workspace/myweb/ --home /home/ubuntu/.virtualenvs/django/ --module myweb.wsgi:application
--http :用于指定端口,这里我指定8888,请先在腾讯云安全组中开放此端口
--chdir:用于指定网站根目录
--home:用于指定虚拟环境地址
--module:用于指定你的Django项目地址
来进行测试(这里的端口可以自己设置,只需访问时记得需改即可)
当然如果有需要可以指定更多的参数:
$ uwsgi --http :8001 --chdir /home/ubuntu/workspace/myweb/ --wsgi-file myweb/wsgi.py --master --processes 4 --threads 2 --stats 127.0.0.1:9191
这里的参数分别代表着
http : 协议类型和端口号
processes : 开启的进程数量
workers : 开启的进程数量,等同于processes(官网的说法是spawn the specified number ofworkers / processes)
chdir : 指定运行目录(chdir to specified directory before apps loading)
wsgi-file : 载入wsgi-file(load .wsgi file)
stats : 在指定的地址上,开启状态服务(enable the stats server on the specified address)
threads : 运行线程。由于GIL的存在,我觉得这个真心没啥用。(run each worker in prethreaded mode with the specified number of threads)
master : 允许主进程存在(enable master process)
daemonize : 使进程在后台运行,并将日志打到指定的日志文件或者udp服务器(daemonize uWSGI)。实际上最常用的,还是把运行记录输出到一个本地文件上。
pidfile : 指定pid文件的位置,记录主进程的pid号。
vacuum : 当服务器退出的时候自动清理环境,删除unix socket文件和pid文件(try to remove all of the generated file/sockets)
如果能拉起的话,就可以来配置nginx和uwsgi了。
接下来,我们就可以将三者结合,来达到预期的效果。
以下是项目所需要的文件。
myweb/
├── manage.py
├── myweb/
│ ├── init.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── myweb_uwsgi.ini
由于在我们通过Django创建myweb项目时,在子目录myweb下已经帮我们生成的 wsgi.py文件。所以,我们只需要再创建myweb_uwsgi.ini配置文件即可,当然,uwsgi支持多种类型的配置文件,如xml,ini等。此处,使用ini类型的配置。这里ini文件创建在项目的主目录下。(可以附上一张tree图)
# myweb_uwsgi.ini file
[uwsgi]
# Django-related settings
;socket= /home/ubuntu/workspace/myweb/uwsgi.sock
# 这里我尝试过使用.sock没有配置成功之后修改为端口之后成功了便没有回来试,有兴趣的朋友可以试试。
# socket的作用是指定项目执行的端口号
socket = 127.0.0.1:8888
# the base directory (full path) 指定项目的目录
chdir = /home/ubuntu/workspace/myweb
wsgi-file = myweb/wsgi.py
# Django s wsgi file
module = myweb.wsgi:application
# 指定虚拟环境的目录
virtualenv = /home/ubuntu/.virtualenvs/django
# process-related settings
# master
master = true
# maximum number of worker processes
processes = 4
# ... with appropriate permissions - may be needed
# chmod-socket = 664
# clear environment on exit
vacuum = true
pidfile = uwsgi.pid
# 服务器启动之后在后台运行,会生成文件uwsgi.log,保存日志信息
daemonize=uwsgi.log
这里的配置,其实等同于在uwsgi的安装过程中使用的wsgi命令,只不过在上文中是通过在命令中添加参数的形式,而这里是将其文件化了。
接下来,就可以在命令行中切换到myweb的项目主目录下,通过uwsgi命令通过读取myweb_uwsgi.ini文件启动项目。
注意查看uwsgi的启动信息,如果有错,就要检查配置文件的参数是否设置有误。
这里记一下uwsgi的配置过程中可能常使用到的命令:
#### 查看uwsgi进程信息:
$ ps -ef | grep uwsgi
#### 启动:
$ uwsgi --ini xxx.ini
#### 重启:
$ uwsgi --reload xxx.pid
#### 停止:
$ uwsgi --stop xxx.pid
这里如果没有pid文件可以通过下面这个命令结束uwsgi进程
$ sudo pkill -f uwsgi -9
或通过以下命令强制关闭全部uwsgi进程
$ ps -aux | grep uwsgi |awk '{print $2}'|xargs kill -9
如果您不是一口气配置完的,可能中间会重新启动服务,忘记了使用 $ workon django 命令进入虚拟环境,可能会导致以下错误:
uwsgi: option ‘–http’ is ambiguous; possibilities: ‘–http-socket’ ‘–http-socket-modifier1’ ‘–http-socket-modifier2’ ‘–https-socket’ ‘–https-socket-modifier1’ ‘–https-socket-modifier2’
getopt_long() error
这里配置nginx.conf,其实是在“/etc/nginx/sites-enabled/mysite.conf” 目录下创建conf文件,所以具体的源文件在哪里都可以,只需要链接到就可以。
sites_availables 指的是所有 nginx 站点;
sites_enabled 指的是当前开启的 nginx 站点;
那这两个文件夹如何配合使用呢?
当需要增加网站时,在 sites_availables 里增加对应的配置文件,当需要启用这个网站的时候,在 sites_enabled 创建对应配置文件的软连接即可:
这里我们将其创建在myweb项目主目录下,通过以下命令进行链接就可以了。
$ sudo ln -s /home/ubuntu/workspace/myweb/mysite_nginx.conf /etc/nginx/sites-enabled/mysite_nginx.conf
mysite_nginx.conf文件的具体内容如下
# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/myweb/mysite.sock; # for a file socket 这里我们同样选择了指定端口的形式
server 127.0.0.1:8888; # for a web port socket (we'll use this first)
}
# configuration of the server
server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name xx.xxx.xxx.xx (或者写域名example.com也可以); # 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 /home/ubuntu/workspace/myweb/media;
# your Django project's media files - amend as required
}
location /static {
alias /home/ubuntu/workspace/myweb/static;
}
# Finally, send all non-media requests to the Django server.
location / {
# uwsgi_pass django;
uwsgi_pass 127.0.0.1:8888;
#这里关于uwsgi_pass这个参数使用两个都可以,但是要确保端口没有被占用,如果使用某一个未成功,可以改为另一个试一下
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
}
另外我们还需要将启动nginx的用户改为root,要不然会出现403 forbidden的错误。使用sudo模式打开/etc/nginx/nginx.conf文件,将第一行中user后面的用户改为root即可。
其实在这里,通过查看配置文件我们可以发现nginx之所以与uwsgi产生关联,是通过以下两行代码实现的
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;include 必须指定为uwsgi_params;而uwsgi_pass指的本机IP的端口与myweb_uwsgi.ini配置文件中的必须一致
配置结束之后重启nginx服务
$ service nginx restart
或者干脆直接全部关闭重启
(django) ubuntu@VM-0-10-ubuntu:~/workspace/myweb$ sudo pkill -f nginx -9
Killed
(django) ubuntu@VM-0-10-ubuntu:~/workspace/myweb$ sudo pkill -f uwsgi -9
Killed
(django) ubuntu@VM-0-10-ubuntu:~/workspace/myweb$ sudo service nginx start
(django) ubuntu@VM-0-10-ubuntu:~/workspace/myweb$ uwsgi --ini myweb_uwsgi.ini
[uWSGI] getting INI configuration from myweb_uwsgi.ini
(django) ubuntu@VM-0-10-ubuntu:~/workspace/myweb$
这时,在浏览器中访问 http://ip:port/ 可以看到,通过此ip和端口的指向,请求会首先到达nginx,如果在此过程执行一些请求,我们可以发现,最终这些请求会转到uwsgi来进行处理。
如果想了解更多关于nginx部署的教程,可以参考Nginx安装部署与测试
参考博客:https://zhuanlan.zhihu.com/p/63038112
暂时还没到这个进度,等到配置之后再来更新。
最后再写一下常用命令:
/etc/init.d/nginx start #启动
/etc/init.d/nginx stop #关闭
/etc/init.d/nginx restart #重启
# 检查nginx配置文件是够有错误
nginx -t
# 重启nginx
service nginx restart
# 查看uwsgi进程
ps -aux | grep uwsgi
# 正常关闭uwsgi进程
uwsgi --stop /home/mysite_uwsgi/master.pid
# 强制关闭全部uwsgi进程
ps -aux | grep uwsgi |awk '{print $2}'|xargs kill -9
# 重新加载uwsgi
uwsgi --reload /home/mysite_uwsgi/master.pid
x lsof -i:9000 #查看端口占用状态
netstat -lnp| grep 9000 #查看端口占用状态
kill -9 +PID号
以上是在Ubuntu18.04上的部署
如果想在Ubuntu16.04部署,大致步骤是一模一样的,只是Ubuntu16.04中预装了python2没有python3,需要自行安装python3和pip3,仅仅多了此步骤而已!
网上的博客比较乱,有的太复杂无法清楚具体的核心,有些过于简单无法直接参考,希望自己在配置过程中整理出来的这篇文章能够帮到你!
5、参考博客及官方文档
[1] https://www.cnblogs.com/zhaoyingjie/p/6840616.html
[2] https://blog.csdn.net/weixin_33943347/article/details/92758875
[3] https://www.cnblogs.com/chenych/p/11075070.html
[4] https://www.jqhtml.com/46328.html
[5] https://www.liyuankun.cn/article/18/
[6] https://zhuanlan.zhihu.com/p/63038112
[7] https://blog.csdn.net/breavo_raw/article/details/82665978