Centos 7下Nginx+uWsgi部署Flask应用

虽然如今docker容器技术成熟且好用,可是Nginx+uWsgi做为经典的web部署仍是快捷而稳定的,因此仍是记录下此次的部署(阿里云服务器),方便之后若是须要的时候翻阅。 环境参数:python

Centos 7
Python 3.6
复制代码

部署前的准备

免密登陆阿里云

阿里云建立完实例后,经过ssh root@xx.xx.xx.xx -p 22输入密码后登陆上云服务(由于是我的使用,我嫌弃每次都须要输入密码就设置了无密码登陆),按如下步骤在服务器上生成密钥对:mysql

[root@iZj6c37pa56zt0xet2tcqeZ ~]# ssh-keygen <== 创建密钥对
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): <== 按 Enter
Enter passphrase (empty for no passphrase): <== 输入密钥锁码,或直接按 Enter 留空
Enter same passphrase again: <== 再输入一遍密钥锁码
Your identification has been saved in /root/.ssh/id_rsa.<== 私钥
Your public key has been saved in /root/.ssh/id_rsa.pub.<== 公钥
The key fingerprint is:
xxxxxxx
复制代码

密钥锁码在使用私钥时必须输入,这样就能够保护私钥不被盗用。固然,也能够留空,实现无密码登陆。 如今,在 root 用户的家目录中生成了一个 .ssh的隐藏目录,内含两个密钥文件:id_rsa 为私钥,id_rsa.pub 为公钥。linux

  1. 在服务器上安装刚刚生成的公钥,并修改文件权限。
[root@iZj6c37pa56zt0xet2tcqeZ ~]# cd .ssh
[root@iZj6c37pa56zt0xet2tcqeZ .ssh]# cat id_rsa.pub >> authorized_keys
[root@iZj6c37pa56zt0xet2tcqeZ .ssh]# chmod 600 authorized_keys 
[root@iZj6c37pa56zt0xet2tcqeZ .ssh]# chmod 700 ~/.ssh
复制代码

这里啰嗦下权限的相关linux知识吧:nginx

  • 修改权限中数字的第一位表示拥有者,第二位是群组,第三位是其余
  • 其中的每一个数字表示读,写,可执行的拥有权限,好比数字600中的数字6,能够拆解成110,1*2^2+1*2^1+0*2^0=6,因此表示文件具备读,写,无可执行权限。
  1. 设置 SSH,打开密钥登陆功能
  • 编辑 /etc/ssh/sshd_config 文件,进行以下设置:
RSAAuthentication yes
PubkeyAuthentication yes
复制代码
  • 另外,请留意 root 用户可否经过 SSH 登陆:PermitRootLogin yes
  • 最后,重启 SSH 服务:service sshd restart
  1. 经过scp命令将私钥下载到本地scp root@xx.xx.xx.xx:/root/.ssh/id_rsa /Users/fangzjty/Desktop/
  2. 在我的用户下找到.ssh位置(我的是mac电脑,windows的机子能够到网上查找下.ssh的位置),而后建立一个mysys-id_rsa文件,名称能够本身取,而后将下载的私钥内容拷贝到这个文件里(固然你也能够直接复制原来的私钥,要不要修更名称看你之后会不会有新的服务)。
  3. 建立一个config文件,在里面输入如下内容并保存
User root
Host xx.xx.xx.xx
IdentityFile ~/.ssh/mysys-id_rsa
Port 22
复制代码

User表示登陆的用户名,Host是你要链接的主机名(域名或者ip地址),IdentityFile表示服务器私钥文件的位置,Port就是登陆的端口git

以上就完成了免密登陆的设置,而后就能够经过ssh root@xx.xx.xx.xx -p 22登陆云服务器了,固然这只是一种设置免密登陆的方式,经过公钥和私钥的配对完成登陆验证,这里是从服务器上拿私钥,你也能够把本身的公钥上传到服务器,写入服务器.ssh下的authorized_keys来容许你的远程免密登陆github

上传项目文件和项目架构

项目架构图以下: web

这里就不用直接建立的工程讲解了,那个比较简单,且不须要安装mysql。该框架下的app.py是项目的启动文件,app核心对象的实例名称也是app。 而后登陆云服务器,建立一个文件夹,命令: mkdir flaskproject 以后将项目上传上这个文件夹下,或者本身上传github,使用 git clone xxxxx命令从github上拉取(github如今支持私有工程了,固然使用git须要安装相应的git命令)。

tar -cvf blog.tar blog/*     <==压缩blog项目,方便上传
scp -r /Users/xxxx/Documents/pyproject/flaskproject/blog.tar root@xx.xx.xx.xx:/root/flaskproject/    <==将本地项目上传到云服务器
tar -xvf blog.tar            <==解压blog项目
复制代码

安装Python环境

yum update   <==更新下yum
yum install zlib-devel bzip2-devel sqlite sqlite-devel openssl-devel
wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz
tar -xvf Python-3.6.3.tgz
cd Python-3.6.3/
./configure       <==编译Python
make
make install
复制代码

若是在./configure时编译失败多是须要安装gcc/g++,此时须要输入:yum install gcc-g++ 安装成功以后,就是建立虚拟环境,能够用virtualenv,virtualenvwrapper或者pipenv,看你我的习惯(python 3.7以上须要安装libffi-devel依赖,执行:yum install libffi-devel -y)。sql

cd                    <==回到主目录
pip3 install --upgrade pip     <==通常会提示你更新pip,由于用的python3,因此更新pip3
pip3 install pipenv
mkdir flaskvenv       <==虚拟环境的文件目录
cd flaskvenv/
mkdir blogvenv
cd blogvenv/
pipenv --python 3.6   <==建立虚拟环境(若是原来是用pipenv的话,直接拷贝Pipfile和Pipfile.lock,而后执行pipenv update便可建立原来的虚拟环境)
pipenv shell          <==运行虚拟环境
pip install -r /root/flaskproject/blog/venv/requirements.txt  <==导入blog项目的依赖库
pipenv graph          <==查看依赖库是否导入
exit                  <==退出虚拟环境
复制代码

pipenv的命令能够经过github上查找项目查看,也能够经过pipenv --help查看命令docker

安装mysql

  1. 安装mysql
wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
yum localinstall mysql57-community-release-el7-8.noarch.rpm
yum repolist enabled | grep "mysql.*-community.*"   <==查看mysql是否安装成功,成功见mysql模块下的图一
yum install mysql-community-server    <==安装mysql
systemctl start mysqld       <==启动mysql服务
systemctl enable mysqld      <==设置开机启动
systemctl daemon-reload
grep 'temporary password' /var/log/mysqld.log  <==查看mysql生成的默认密码
mysql -uroot -p              <==输入默认密码
复制代码

进入mysql以后:shell

mysql> set password for 'root'@'localhost'=password('YourPassword');   <==修改密码
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '你的密码' WITH GRANT OPTION;      <==赋予权限全部远程主机都能链接上mysql
mysql> FLUSH PRIVILEGES;
复制代码

重启mysql:systemctl restart mysqld

图一:

设置密码有必定规则,若是想简单点能够把规则关掉或者下降规则标准: mysql> set global validate_password_policy=0;

Mysql为了安全性,在默认状况下用户只容许在本地登陆,可使用以上方法,固然也能够经过给固定用户分配权限的方式实现。

  1. 测试mysql的外部链接 要链接上阿里云上的服务,须要在阿里云的安全组中开放端口,具体规则阿里云上描述的比较详细了,就不说了,在阿里云上加上3306的端口便可。 而后在本地中经过可视化mysql的相关工具进行连通测试,显示链接成功。

  2. 建立对应数据库 根据你本身的项目须要建立对应的数据库

uwsgi安装

  1. 安装uwsgi
pip3 install uwsgi        <==安装uwsgi
cd /root/flaskproject/blog
vim uwsgi_blog.ini
复制代码

uwsgi_blog.ini的配置内容以下

[uwsgi]
chdir = /root/flaskproject/blog
socket = /root/flaskproject/blog/script/uwsgi.sock
#socket = 127.0.0.1:3021
master = 1
processes = 2
virtualenv=/root/.local/share/virtualenvs/blogvenv-7HO3iOv9
callable = app
wsgi-file = app.py
logto=/root/flasklog/blog/uwsgi.log
复制代码
  • chdir表示运行目录
  • socket是用于和nginx交互的连通网络(docker中的network),2个本地的应用若是须要交互,须要有一个连通桥梁,这个socker就是nginx和uwsgi的连通桥梁。可使用IP+端口,也可使用.sock文件进行连通(.scok文件建立稍后描述)
  • master主进程数量
  • processes子进程数量
  • virtualenv虚拟环境地址,这个地址经过在cd /root/flaskvenv/blogvenv,而后经过pipenv --venv获取到
  • callable表示flask项目实例的名称,好比代码中app = Flask(name),因此这里为app
  • wsgi-file项目的启动文件
  • logtouwsgi的日志(将日志打到指定的日志文件,若是使用“daemonize=”的话会致使supervisor守护进程失败,由于设置daemonize在将日志记录到文件的同时,也会让uWSGI进程进入后台守护uWSGI,而supervisor自己就已经起到了守护进程的做用,会报以下错误:uwsgi FATAL Exited too quickly (process log may have details))

建立uwsgi.sock文件

cd /root/flaskproject/blog
mkdir script
cd script
touch uwsgi.sock
chmod 666 uwsgi.sock
cd ..
chmod 666 script
复制代码
  1. 测试uwsgi 使用uwsgi --ini /root/flaskproject/blog/uwsgi_blog.ini测试uwsgi是否成功,成功则会出现如下提示: [uWSGI] getting INI configuration from /root/flaskproject/blog/uwsgi_blog.ini 而后查看uwsgi.log是否有错误信息:more /root/flasklog/blog/uwsgi.log。若是没有错误而且有相似信息则表示uwsgi安装和部署没有问题: WSGI app 0 (mountpoint='') ready in 0 seconds on interpreter 0x1bb0880 pid: 18601 (default app)

若是出现相似unable to load app 0 (mountpoint='') (callable not found or import error)信息,那大几率是你uwsgi_blog.ini的配置出现问题了,看看各参数和说明(备注:数据库记得先建立,若是有使用APScheduler定时任务(或者须要多线程状况下),在uwsgi.ini中配置 enable-threads = true preload=True lazy-apps=true)。

nginx安装

yum install nginx
cd /root/flaskproject/blog
vim nginx_blog.conf
复制代码

nginx_blog.conf的内容以下:

server {
       listen      8021;       #监听端口
       server_name xx.xx.xx.xx;    #服务器公网IP或者域名
       charset     utf-8;
       access_log  /root/flasklog/blog/access.log;
       error_log  /root/flasklog/blog/error.log;

       location  /  {
          include      uwsgi_params;
          # uwsgi_pass 127.0.0.1:3021;
          uwsgi_pass   unix:/root/flaskproject/blog/script/uwsgi.sock;
          # uwsgi_param UWSGI_PYHOME /root/.local/share/virtualenvs/blogvenv-lyQ6xKaC; # 指向虚拟环境目录
          # uwsgi_param UWSGI_CHDIR /root/flaskproject/blog; # 指向网站根目录
          # uwsgi_param UWSGI_SCRIPT app; # 指定启动程序
       }
    }
复制代码

填写好本身须要暴露出来的端口和公网ip,并建立access_log和error_log文件,uwsgi_pass就是链接uwsgi的桥梁,保持和uwsgi中的配置一致就行了。 以后将该配置软链接到conf.d目录下:ln -s /root/flaskproject/blog/nginx_blog.conf /etc/nginx/conf.d/,由于nginx.conf中会include下的全部文件(见nginx.conf的配置文件),因此只要连接到该目录下,也只用添加server就能够了。

nginx -t -c /etc/nginx/nginx.conf    <==检查nginx配置是否有语法错误
systemctl start nginx.service        <==启动nginx
复制代码

这时候,若是你是用uwsgi.sock来做为桥梁沟通,就会有问题,你能够经过curl 127.0.0.1:port(port更换为你要测试的端口号),而后就能够到你本身建立的nginx的error.log中查看到错误信息,发现提示:“1 connect() to unix:/root/flaskproject/blog /script/uwsgi.sock failed (13: Permission denied) while connecting to upstream。”,说的是没有链接uwsgi.sock的权限,但是明明开放了全部权限的,这点我也不是很明白,而后经过修改nginx.conf的下的用户组解决这个问题:vim /etc/nginx/nginx.conf,以后修改第一个的user nginx;user root;而后从新启动nginx:nginx -s reload

这时,nginx的部署在本地就成功了,而后须要到阿里云的安全组下开通端口,好比我上面须要开8021端口。以后在若是没法链接可能由于防火墙拦截了,须要让该端口能够被防火墙放行(Centos 7以上是firewall,Centos 6上是iptables,虽然firewall也是基于iptables上实现的):

firewall-cmd --zone=public --add-port=8021/tcp --permanent 
firewall-cmd --reload
复制代码

至此,你就能够经过外网的地址访问服务了。记得在你每作完一个功能块的时候测试下是否成功,省得最后的时候去测试但找不到来是那块出了问题。

资源:

相关文章
相关标签/搜索