项目环境:python2.7, django1.9, ubuntu(阿里云服务器)
1.利用scp将项目传上阿里云服务器,运行开发服务器测试
(下面的项目名我都用projectname表示)运行命令:
cd projectname # 进入项目projectname目录
python manage.py runserver 0.0.0.0:8000
(运行开发服务器测试,确保开发服务器能正常打开网站)
这里有一个简易的办法让项目一直在后台运行:nohup,进入项目目录下运行命令:
nuhup python manage.py runserver 0.0.0.0:8000&
在当前目录下会生成一个nohup.out文件,项目的输出信息全在里面,错误信息可从里面查找。但这不叫部署,下面开始部署。
2. 安装nginx 和需要的包
2.1 安装 nginx 等软件
ubuntu / Linux Mint 等,下面简写为 (ubuntu):
sudoapt-get install python-dev nginx
2.2 安装 supervisor, 一个专门用来管理进程的工具,我们用它来管理 uwsgi 进程
sudopip install supervisor
在这有一个问题需要注意一下的就是,如果你是centOS用户,不是则直接进入3,请先查看一下你的seLinux是否开启,因为其存在安全性问题,会导致后面你利用nginx做反向代理你的项目时访问被拒绝。运行命令,将 SELinux 设置为宽容模式,方便调试:
sudo setenforce 0
防火墙相关的设置:
可以选择临时关闭防火墙
sudo service iptables stop
或者开放一些需要的端口,比如 8002
sudo iptables -A INPUT -p tcp -m tcp --dport 8002 -j ACCEPT
上面的两条命令,如果是 CentOS用户用
临时关闭防火墙
sudo systemctl stop firewalld
或者 开放需要的端口
sudo firewall-cmd --zone=public --add-port=80/tcp--permanent
sudo firewall-cmd --reload
3.使用uwsgi来部署
安装uwsgi
sudo pip install uwsgi --upgrade
使用uwsgi 运行项目(我的项目放在/root下)
uwsgi --http :8002 --chidir /root/projectname --home=/path/to/venv --module project.wsgi
这样就可以跑了,--home 指定virtualenv 路径,如果没有可以去掉。project.wsgi 指的是 project/wsgi.py 文件.
如果想安装virtualenv可以按下面步骤安装,不想则略过直接到4:
为什么要安装virtualenv?答案来自”廖雪峰python“(在开发Python应用程序的时候,系统安装的Python3只有一个版本:3.4。所有第三方的包都会被pip安装到Python3的site-packages目录下。如果我们要同时开发多个应用程序,那这些应用程序都会共用一个Python,就是安装在系统的Python 3。如果应用A需要jinja 2.7,而应用B需要jinja 2.6怎么办?这种情况下,每个应用可能需要各自拥有一套“独立”的Python运行环境。virtualenv就是用来为一个应用创建一套“隔离”的Python运行环境。)
下面开始安装:
pip install virtualenv
然后,假定我们要开发一个新的项目,需要一套独立的Python运行环境,可以这么做:
第一步,创建目录:
mkdir myproject
cd myproject
第二步,创建一个独立的Python运行环境,命名为venv:
virtualenv --no-site-packages venv
命令virtualenv就可以创建一个独立的Python运行环境,我们还加上了参数--no-site-packages,这样,已经安装到系统Python环境中的所有第三方包都不会复制过来,这样,我们就得到了一个不带任何第三方包的“干净”的Python运行环境。
建的Python环境被放到当前目录下的venv目录。有了venv这个Python环境,可以用source进入该环境:
source venv/bin/activate
注意到命令提示符变了,有个(venv)前缀,表示当前环境是一个名为venv的Python环境。下面你就可以正常安装各种你想要的第三方包,运行python命令
在venv环境下,用pip安装的包都被安装到venv这个环境下,系统Python环境不受任何影响。也就是说,venv环境是专门针对myproject这个应用创建的。
退出当前的venv环境,使用deactivate命令:
deactivate
此时就回到了正常的环境,现在pip或python均是在系统Python环境下执行。
3.1 查询端口
如果在3中出现端口被占的情况,通过命令查询端口:
lsof -i:8002
再利用查询到的pid,通过kill命令关掉相关程序:
kill -9 pid
或者按程序名称查询:以下两个命令都一样的效果,只是显示略有区别:
ps -ef | grep uwsgi
ps aux | grep uwsgi
4.使用supervisor来管理进程
安装 supervisor 软件包
(sudo) pip install supervisor
生成 supervisor 默认配置文件,比如我们放在 /etc/supervisord.conf 路径中:
(sudo) echo_supervisord_conf > /etc/supervisord.conf
打开 supervisord.conf 在最底部添加(每一行前面不要有空格,防止报错):
[program:projectname]
command=/path/to/uwsgi --http :8002 --chdir /path/to/projectname --module projectname.wsgi
directory=/path/to/projectname
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
command 中写上对应的命令,这样,就可以用 supervisor 来管理了。
启动 supervisor:
(sudo) supervisord -c /etc/supervisord.conf
重启 projectname 程序(项目):
(sudo) supervisorctl -c /etc/supervisord.conf restart projectname
启动,停止,或重启 supervisor 管理的某个程序 或 所有程序:
(sudo) supervisorctl -c /etc/supervisord.conf [start|stop|restart] [program-name|all]
以 uwsgi 为例,上面这样使用一行命令太长了,我们使用 ini 配置文件来搞定,比如项目在 /root/projectname 这个位置,
在其中新建一个 uwsgi.ini 全路径为 /root/projectname/uwsgi.ini
[uwsgi]
socket = /root/projectname/projectname.sock
chdir =/root/projectname
wsgi-file= projectname/wsgi.py
touch-reload = /root/projectname/reload
processes = 2
threads = 4
chmod-socket = 666
chown-socket =www-data:www-data
vacuum = true
在这有几个要注意的问题:
(1)./root/projectname/projectname.sock ,待会配置nginx时我们把它和nginx关联起来,在这我们采用的sock方式通信,也可以直接采用ip地址加端口的形式,比如socket=127.0.0.1:8003,则后面配置nginx的时候也要写成一样的就行。
(2).chmod-socket = 666 ,chown-socket =www-data:www-data有些人在后面可能会出现权限问题,所以在这直接设好,还有chown-socket设置,也就是gid,uid设置
(3).不建议把 sock 文件放在 /tmp 下,比如 /tmp/xxx.sock (不建议)!有些系统的临时文件是 namespaced 的,进程只能看到自己的临时文件,导致 nginx 找不到 uwsgi 的 socket 文件,访问时显示502,nginx 的 access log 中显示 unix: /tmp/xxx.sock failed (2: No such file or directory),所以部署的时候建议用其它目录来放 socket 文件,比如放在运行nginx用户目录中,也可以专门弄一个目录来存放 sock 文件,比如 /tmp2/
sudomkdir-p /tmp2/&& sudochmod777 /tmp2/
然后可以用 /tmp2/projectname.sock 这样的路径了。
修改 supervisor 配置文件中的 command 一行:
[program:projectname]
command=/path/to/uwsgi --ini /root/projectname/uwsgi.ini
directory=/root/projectname(我的项目是放在/root下,你们按照你们的即可)
startsecs=0
5.配置 Nginx
在nginx下新建一个自己的项目projectname
sudo vim /etc/nginx/sites-available/projectname.conf
写入以下内容:
server {
listen 8002;
server_name localhost; #有域名写域名,没域名写localhost或者" _" 或者公网ip
charset utf-8;
client_max_body_size 75M;
location /media {
alias /path/to/project/media;
}
location /static {
alias /path/to/project/static;
}
location / {
uwsgi_pass unix:///root/peojectname/projectname.sock;
include /etc/nginx/uwsgi_params;
}
}
激活项目:
sudo ln -s /etc/nginx/sites-available/projectname.conf /etc/nginx/sites-enabled/projectname.conf
测试配置语法问题:
sudo service nginx configtest
如果显示fail,则通过下面命令查看具体原因:
sudo nginx -t
重启 nginx 服务器:
sudo service nginx reload 或 sudo service nginx restart 或 /path/to/nginx -s reload
如果启动成功,则说明目前配置没有问题,如果启动失败,则应该是nginx配置没配好。
6.总结:
我在配置的时候出现的很多问题现总结如下:
(1)nginx配置之后测试成功,但启动失败,当时配置的时候我发现是/etc/nginx/nginx.conf 文件被我不知道怎么给修改了,导致出现server not allow here.是因为nginx读取了/etc/nginx/sites-available/projectname.conf里面的配置,而这里面又没有http。projectname.conf这个文件应该是include在/etc/nginx/nginx.conf 文件里面的,修改回来之后则nginx启动成功。
(2)nginx启动成功了,但是没有成功代理项目,我用superivsorctl启动项目之后发现可以直接通过8002端口访问项目,nginx监听8002端口启动失败,查看原因发现地址被占,停止supervisorctl之后8002端口被放出,我在/etc/supervisord.conf和uwsgi.ini中均未指定端口,原因可能是superivsorctl在启动时启动了我其他时候配置过的项目或者运行了我之前利用uwsgi测试项目的命令,导致端口被占用。此时我考虑换一个端口8003,启动成功,但访问页面时失败。
分析是uwsgi.ini配置了端口还是superivsorctl配置了端口,我先单独运行uwsgi --ini uwsgi.ini 发现成功运行且未占用端口,显然是因为运行superivsorctl占用了端口。
(3)基于此考虑暂时放弃supervisor, 考虑先利用uwsgi --ini uwsgi.ini 命令在前台运行,端口未被占,nginx监听8002端口,启动成功,访问页面出现502,查看错误日志/var/log/nginx/error.log,发现是(13,permission deny),
a.查看网上资料发现很多人因为用的是centOS系统,出现seLinux安全性问题,一般解决方案关掉就行,上面我已经写了,
b.第二种情况是说权限问题,将chmod-socket = 666 ,chown-socket =www-data:www-data设置成这个,这里有一个问题就是,因为我是采用sock通信,启动uwsgi自动生成.sock文件,虽然我修改了权限,你会发现生成的sock文件权限并没有变化,这时你应该删除现在的sock文件,重新启动uwsgi,然后在启动nginx,看看你们有没有解决问题,
c.但我仍然没有解决问题,最后原因发现了是因为我用root身份运行的uwsgi,在/etc/nginx/nginx.conf里面的用户却是www-data,将其改成root之后,成功访问。
(4)之前我用uwsgi在前台通过设置http端口命令运行项目的时候发现static静态资源文件加载不出来,那是因为uwsgi没有理会静态资源文件,通过nginx反向代理之后,静态资源文件成功加载。
(5)还有一个问题没有解决就是,我的uwsgi是在前台运行的,supervisor又会出现莫名奇妙的8002端口占用,查看uwsgi进行发现有很多个进程在运行,这里考虑使用nohup 将uwsgi在后台运行,命令:
nohup uwsgi --ini uwsgi.ini&
重启nginx:
sudo service nginx restart
成功实现代理。
后期继续研究这个supervisor占用我8002端口的问题,从性能上利用supervisor管理uwsgi肯定比nohup更好。