最近在看關於Docker和Nginx方面的內容,先於在Docker上開發以及部署python應用自然要先能夠在本機上部署,其中找到一篇文章寫的最為詳細並且實驗成功,所以在此翻譯轉載過來以備后需。【原文鏈接】
簡介:
這篇文章將介紹在ubuntu14.04環境下使用nginx作為反向代理服務器,uWSGI作為服務器來部署最簡單的flask應用。
(也就是瀏覽器發送的web request先到達Nginx服務器,而后Nginx服務器再將其轉發到uWSGI服務器做實際處理)
前提要求:
首先需要一個擁有可執行sudo命令的非root用戶。
WSGI:web server gateway interface,其是一種網絡服務接口,通過它我們可以忽略掉網絡請求與返回響應的具體細節而專注於處理邏輯,是一種通信協議。【廖雪峰的WSGI教程】
uwsgi: 是一個基於二進制的線路協議(wire protocol),被uWSGI應用服務器實現來用於與功能更加強大的web服務器做通信。
uWSGI:一個實現了WSGI以及uwsgi通信協議的應用服務器。【文檔】
安裝所需組件:
sudo apt-get update
sudo apt-get install python-pip python-dev nginx
sudo pip install virtualenv #安裝virtualenv
mkdir ~/myproject #創建實際要用到的目錄
cd ~/myproject
virtualenv myprojectenv #創建虛擬環境myprojectenv
source myprojectenv/bin/activate #激活虛擬環境
創建一個flask應用
注:現在在虛擬環境中,並且在~/myproject目錄下
安裝Flask與uwsgi
pip install uwsgi flask
創建flask app:
#/myproject/myproject.py
from flask import Flask application = Flask(__name__) @application.route("/") def hello(): return "<h1 style='color:blue'>Hello There!</h1>" if __name__ == "__main__": application.run(host='0.0.0.0')
#注,現在python myproject.py即能夠在瀏覽器中看到輸出
創建WSGI接入點
接下來我們將創建一個文件作為我們的flask應用與uWSGI服務器的接入點,這用於告訴uWSGI如何調用我們的應用:
# ~/myproject/wsgi.py
from myproject import application
if __name__ == "__main__":
application.run()
配置uWSGI:
目前應用以及接入點都創建好了,接下來處理uWSGI的配置
測試uWSGI服務器可用:
可以通過我們上面設置的接入點文件來做測試, We'll also specify the socket so that it will be started on a publicly available interface and the protocol so that it will use HTTP instead of the uwsgi
binary protocol:
uwsgi --socket 0.0.0.0:8000 --protocol=http -w wsgi
這時通過ip:8000就應該能夠訪問到上面flask應用的輸出,表明uWSGI服務沒有問題
到此虛擬環境就可以關閉了:
deactivate
創建uwsgi配置文件:
上面已經測試了uWSGI可以用於作為服務器來呈現應用,但為了獲得更好的性能,還需要對其進行配置
# ~/myproject/myproject.ini
[uwsgi] # uWSGI識別符,從而要執行下面的setting
module = wsgi # 申明使用wsgi.py模塊
master = true #啟動master模式
processes = 5 #調用5個進程用於處理連接
#在上面的測試中,我們將uWSGI暴露到了8000端口,但是在這里我們使用Nginx來獲取客戶端連接,隨后才將其轉發到uWSGI服務器
#由於他們都在同一機器上,使用一個Unix socket來傳遞將更加安全快速,我們設置其為myproject.sock並且放到myproject目錄下
#並且,我們需要改變其權限,在隨后我們將獲得Nginx group對於uWSGI進程的所有權,所以我們需要保證此socket能夠讀寫
#與此同時通過設置vacuum來達到進程結束后清理此socket的設計
socket = myproject.sock chmod-socket = 660 vacuum = true
#die-on-term
option:because the Upstart init system and uWSGI have different ideas on what different process signals should mean.
# Setting this aligns the two system components, implementing the expected behavior:
die-on-term = true
注:你會發現配置文件並沒有像命令行啟動樣指明所用協議,那是因為默認的uWSGI就使用uwsgi協議【一種快速的用於與其他服務器交流的二進制協議,此比使用HTTP協議高效】
創建啟動腳本:
創建啟動腳本的目的是讓ubuntu能夠自動啟動uWSGI服務器來啟動我們的flask應用
$sudo vim /etc/init/myproject.conf
#操作系統有不同的runlevel,通過下面的設置既是開機啟動,關機(重啟,單一用戶模式)時關閉
description "uWSGI server instance configured to serve myproject"
start on runlevel [2345]
stop on runlevel [!2345]
#設置uWSGI運行時的用戶以及用戶組,
setuid user
setgid www-data #Nginx在www-data用戶組下,所以這里需要設置為www-data從而使其可以讀寫socket文件
env PATH=/home/user/myproject/myprojectenv/bin #設置使用的虛擬環境的地址
chdir /home/user/myproject #切換到應用目錄
exec uwsgi --ini myproject.ini #Afterwards, we can simply call the uWSGI executable and pass it the configuration file we wrote:
在上面配置完成推出后可通過下面語句啟動:
sudo start myproject
注:此語句會提供是否啟動成功的提示
配置Nginx代理請求:
目前,我們的uWSGI應用服務已經開始運行了,正在等待socket文件中的請求,接下來我們就來設置Nginx來使用uwsgi協議傳遞web request到socket文件
在Nginx的sites-available目錄下創建一個新的server模塊配置文件:
$sudo vim /etc/nginx/sites-available/myproject
server {
listen 80; #監聽80端口
server_name server_domain_or_IP; #設置主機名或主機IP location / { #當使用瀏覽器訪問主頁時 include uwsgi_params; #使用uwsgi_para文件設置一些常用的uWSGI參數 uwsgi_pass unix:/home/user/myproject/myproject.sock; #使用uwsgi_pass把request傳遞到socket文件 }
}
關閉文件
通過link以上配置文件到site-enable目錄來激活上面的配置:
sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
可以通過一下語句檢查語法錯誤:
sudo nginx -t
如果沒有問題,通過以下語句重啟Nginx服務來讀取新的配置:
sudo service nginx restart
好了,現在就大功搞成了,通過瀏覽器就能夠訪問到我們的上面的flask應用了
總結:
這篇文章,我們在虛擬環境下創建了一個flask應用,通過創建WSGI接入點使得所有WSGI-capable的應用能夠與之交互,並且配置了uWSGI服務器提供此功能,然后,我們創建了一個能夠自動啟動應用的腳本。隨后我們配置了Nginx的server模塊來傳遞web request到應用服務器。
外記:
在試驗成功作者的案例后,我准備在我的服務器上部署下這篇文章提到的我以前用flask做的簡易博客,我在其過程中遇到了兩個問題:
1:如何在virtual環境下安裝MySQLdb模塊,總所周知,在ubuntu中我們使用apt-get install python-mysqldb來安裝,在激活了虛擬環境使用這個安裝后進入python使用import MySQLdb依然會報錯沒有此模塊,當然,使用pip install MySQL-python也是不行的,后來查了會兒發現有兩種解決方法一時在虛擬環境時使用--system-site-package,這是由於默認的是--no-site-package,也就是不帶有原python安裝了的庫,另一個說法是其實是可以使用pip安裝的,只是先要安裝相關依賴。我覺得最好的辦法是部分使用第一種,也就是在創建虛擬環境時是不是可以部分的引入包,這個尚待明天研究
2:在使用--system-site-package解決了上面的問題后一切都很順利,當滿懷欣喜准備打開網站時彈出了以下東東:
(注:服務器和域名都是在阿里雲上買的)
注:關於用uwsgi與nginx同理部署Django的鏈接
uwsgi文檔,其講的十分全面