Centos 7下Nginx+uWsgi部署Flask應用

zjty發表於2019-04-05

雖然現在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 為公鑰。

  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知識吧:

  • 修改許可權中數字的第一位表示擁有者,第二位是群組,第三位是其他
  • 其中的每個數字表示讀,寫,可執行的擁有許可權,比如數字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檔案,名稱可以自己取,然後將下載的私鑰內容拷貝到這個檔案裡(當然你也可以直接複製原來的私鑰,要不要修改名稱看你以後會不會有新的服務)。
    Centos 7下Nginx+uWsgi部署Flask應用
  3. 建立一個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來允許你的遠端免密登入

上傳專案檔案和專案架構

專案架構圖如下:

Centos 7下Nginx+uWsgi部署Flask應用
這裡就不用直接建立的工程講解了,那個比較簡單,且不需要安裝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,看你個人習慣。

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

  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之後:

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

圖一:

Centos 7下Nginx+uWsgi部署Flask應用
設定密碼有一定規則,如果想簡單點可以把規則關掉或者降低規則標準: 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
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
複製程式碼
  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的配置出現問題了,看看各引數和說明。

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
複製程式碼

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

資源:

相關文章