虽然现在docker容器技术成熟且好用,但是Nginx+uWsgi作为经典的web部署还是快捷而稳定的,所以还是记录下这次的部署(阿里云服务器),方便以后如果需要的时候翻阅。 环境参数:
Centos 7
Python 3.6
复制代码
部署前的准备
免密登录阿里云
阿里云创建完实例后,通过ssh root@xx.xx.xx.xx -p 22
输入密码后登录上云服务(因为是个人使用,我嫌弃每次都需要输入密码就设置了无密码登录),按以下步骤在服务器上生成密钥对:
[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 为公钥。
- 在服务器上安装刚刚生成的公钥,并修改文件权限。
[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知识吧:
- 修改权限中数字的第一位表示拥有者,第二位是群组,第三位是其他
- 其中的每个数字表示读,写,可执行的拥有权限,比如数字600中的数字6,可以拆解成110,
1*2^2+1*2^1+0*2^0=6
,所以表示文件具有读,写,无可执行权限。
- 设置 SSH,打开密钥登录功能
- 编辑 /etc/ssh/sshd_config 文件,进行如下设置:
RSAAuthentication yes
PubkeyAuthentication yes
复制代码
- 另外,请留意 root 用户能否通过 SSH 登录:
PermitRootLogin yes
- 最后,重启 SSH 服务:
service sshd restart
- 通过scp命令将私钥下载到本地
scp root@xx.xx.xx.xx:/root/.ssh/id_rsa /Users/fangzjty/Desktop/
。 - 在个人用户下找到.ssh位置(个人是mac电脑,windows的机子可以到网上查找下.ssh的位置),然后创建一个
mysys-id_rsa
文件,名称可以自己取,然后将下载的私钥内容拷贝到这个文件里(当然你也可以直接复制原来的私钥,要不要修改名称看你以后会不会有新的服务)。 - 创建一个config文件,在里面输入以下内容并保存
User root
Host xx.xx.xx.xx
IdentityFile ~/.ssh/mysys-id_rsa
Port 22
复制代码
User表示登录的用户名,Host是你要连接的主机名(域名或者ip地址),IdentityFile表示服务器私钥文件的位置,Port就是登录的端口
以上就完成了免密登录的设置,然后就可以通过ssh root@xx.xx.xx.xx -p 22
登录云服务器了,当然这只是一种设置免密登录的方式,通过公钥和私钥的配对完成登录验证,这里是从服务器上拿私钥,你也可以把自己的公钥上传到服务器,写入服务器.ssh下的authorized_keys来允许你的远程免密登录
上传项目文件和项目架构
项目架构图如下:
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,看你个人习惯。
cd <==回到主目录
pip3 install --upgrade pip <==一般会提示你更新pip,因为用的python3,所以更新pip3
pip3 install pipenv
mkdir flaskvenv <==虚拟环境的文件目录
cd flaskvenv/
mkdir blogvenv
cd blogvenv/
pipenv --python 3.6 <==创建虚拟环境
pipenv shell <==运行虚拟环境
pip install -r /root/flaskproject/blog/venv/requirements.txt <==导入blog项目的依赖库
pipenv graph <==查看依赖库是否导入
exit <==退出虚拟环境
复制代码
pipenv的命令可以通过github上查找项目查看,也可以通过pipenv --help查看命令
安装mysql
- 安装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之后:
mysql> set password for 'root'@'localhost'=password('YourPassword'); <==修改密码
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'xxxxx' WITH GRANT OPTION; <==赋予权限所有远程主机都能连接上mysql
mysql> FLUSH PRIVILEGES;
复制代码
重启mysql:systemctl restart mysqld
图一:
mysql> set global validate_password_policy=0;
Mysql为了安全性,在默认情况下用户只允许在本地登录,可以使用以上方法,当然也可以通过给固定用户分配权限的方式实现。
-
测试mysql的外部连接 要连接上阿里云上的服务,需要在阿里云的安全组中开放端口,具体规则阿里云上描述的比较详细了,就不说了,在阿里云上加上3306的端口即可。 然后在本地中通过可视化mysql的相关工具进行连通测试,显示连接成功。
-
创建对应数据库 根据你自己的项目需要创建对应的数据库
uwsgi安装
- 安装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
daemonize=/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项目的启动文件
- daemonizeuwsgi的日志(这个文件自己根据路径来创建文件和文件夹,这里就不说了)
创建uwsgi.sock文件
cd /root/flaskproject/blog
mkdir script
cd script
touch uwsgi.sock
chmod 666 uwsgi.sock
cd ..
chmod 666 script
复制代码
- 测试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的配置出现问题了,看看各参数和说明。
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
复制代码
至此,你就可以通过外网的地址访问服务了。记得在你没做完一个功能块的时候测试下是否成功,免得最后的时候去测试但找不到来是那块出了问题。
资源: