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
複製代碼

至此,你就能夠經過外網的地址訪問服務了。記得在你每作完一個功能塊的時候測試下是否成功,省得最後的時候去測試但找不到來是那塊出了問題。

資源:

相關文章
相關標籤/搜索