在 Ubuntu 上使用 Nginx 部署 Flask 應用

發表於2016-02-02

我職業生涯的大部分都在使用微軟的架構,最近我決定走出技術的舒適區,步入開源軟體世界。我現在日常工作的專案是一個RESTful服務,這個服務需要在主流硬體上執行,且能夠按照需要進行水平擴充。為完成這項工作我決定使用Flask和Nginx。Flask是一個輕量級的Python Web框架,Nginx是一個非常穩定的Web伺服器,它們在廉價硬體平臺上工作良好。

在這篇文章中我將指導你完成使用Nginx伺服器託管Flask應用的安裝、配置過程。我所使用的作業系統是Ubuntu 13.04。

前提條件

在我們開始安裝Nginx及其他所需軟體之前先安裝一些前提軟體。首先,我們需要PIP與virtualenv:

使用apt-get安裝Nginx的話,我們需要新增Nginx庫到apt-get source中:

注意:如果“add-apt-repository”命令在你的Ubuntu版本中不存在的話,你需要安裝“software-properties-common”包,使用命令:sudo apt-get software-properties-common(感謝get_with_it在評論中提到)

升級已有的包,確保系統上有uWSGI所需的編譯器和工具:

Nginx

安裝並執行Nginx:

Nginx是一個提供靜態檔案訪問的web服務,然而,它不能直接執行託管Python應用程式,而uWSGI解決了這個問題。讓我們先安裝uWSGI,稍候再配置Nginx和uWSGI之間的互動。

里程碑 #1

開啟瀏覽器訪問你的伺服器,你應該能看到Nginx歡迎頁:

nginx

示例應用

我們將託管的應用是經典的“Hello, world!”。這個應用只有一個頁面,已經猜到頁面上將有什麼內容了吧。將所有應用相關的檔案存放在/var/www/demoapp資料夾中。下面建立這個資料夾並在其中初始化一個虛擬環境:

由於我們使用root許可權建立了這個資料夾,它目前歸root使用者所有,讓我們更改它的所有權給你登入的使用者(我的例子中是ubuntu)

建立並啟用一個虛擬環境,在其中安裝Flask:

使用下面的程式碼建立hello.py檔案:

里程碑 #2

讓我們執行我們剛建立的指令碼:

現在你可以通過瀏覽器訪問你伺服器的8080埠,看,應用生效了:

flask

注意:因為80埠已被Nginx使用,這裡我使用8080埠。

現在應用是由Flask內建的web服務託管的,對於開發和除錯這確實是個不錯的工具,但不推薦在生產環境中使用。讓我們配置Nginx來挑起這個重擔吧。

配置Nginx

首先刪除掉Nginx的預設配置檔案:

注意:如果你安裝了其他版本的Nginx,預設配置檔案可能在/etc/nginx/conf.d資料夾下

建立一個我們應用使用的新配置檔案/var/www/demoapp/demoapp_nginx.conf

將剛建立的配置檔案使用符號連結到Nginx配置檔案資料夾中,重啟Nginx:

里程碑 #3

訪問伺服器的公共ip地址,你會看到一個錯誤:

502

別擔心,這個錯誤是正常的,它代表Nginx已經使用了我們新建立的配置檔案,但在連結到我們的Python應用閘道器uWSGI時遇到了問題。到uWSGI的連結在Nginx配置檔案的第10行定義:

這代表Nginx和uWSGI之間的連結是通過一個socket檔案,這個檔案位於/var/www/demoapp/demoapp_uwsgi.sock。因為我們還沒有配置uWSGI,所以這個檔案還不存在,因此Nginx返回“bad gateway”錯誤,讓我們馬上修正它吧。

配置uWSGI

建立一個新的uWSGI配置檔案/var/www/demoapp/demoapp_uwsgi.ini

建立一個新資料夾存放uWSGI日誌,更改資料夾的所有權:

里程碑 #4

執行uWSGI,用新建立的配置檔案作為引數:

接下來訪問你的伺服器,現在Nginx可以連線到uWSGI程式了:

uwsgi

我們現在基本完成了,唯一剩下的事情是配置uWSGI在後臺執行,這是uWSGI Emperor的職責。

uWSGI Emperor

uWSGI Emperor (很拉風的名字,是不?) 負責讀取配置檔案並且生成uWSGI程式來執行它們。建立一個初始配置來執行emperor – /etc/init/uwsgi.conf

最後一行執行uWSGI守護程式並讓它到/etc/uwsgi/vassals資料夾查詢配置檔案。建立這個資料夾,在其中建立一個到鏈到我們剛建立配置檔案的符號連結。

同時,最後一行說明用來執行守護程式的使用者是www-data。為簡單起見,將這個使用者設定成應用和日誌資料夾的所有者。

注意:我們先前安裝的Nginx版本使用“www-data”這個使用者來執行Nginx,其他Nginx版本的可能使用“Nginx”這個替代使用者

由於Nginx和uWSGI都由同一個使用者執行,我們可以在uWSGI配置中新增一個安全提升項。開啟uWSGI配置檔案,將chmod-socket值由666更改為644

現在我們可以執行uWSGI了:

最後,Nginx和uWSGI被配置成啟動後立即對外提供我們的應用服務。

問題解決

如果出現錯誤的話,第一個檢查的地方是日誌檔案。Nginx預設將錯誤資訊寫到/var/log/nginx/errors.log檔案。

我們已經配置了uWSGI emperor將日誌寫到/var/log/uwsgi/emperor.log。這個資料夾還包含著每個配置應用的單獨日誌。我們的例子是 – /var/log/uwsgi/demoapp_uwsgi.log

靜態檔案

如果你的應用提供靜態檔案的話,將下面的規則新增到demoapp_nginx.conf檔案:

上面配置的結果就是所有在/var/www/demoapp/static資料夾中的檔案將由提供Nginx對外服務(謝謝Bastianh指出)

託管多個應用

如果你想在一臺伺服器上託管多個Flask應用,為每個應用建立一個單獨的資料夾,像我們前面所做的一樣,建立Nginx及uWSGI配置檔案到應用資料夾的符號連結。

使用Distribute部署應用

使用distribute部署Flask應用的話,首先,按照Flask文件裡的步驟將應用轉化成package,然後複製distribute通用安裝包到伺服器上,使用虛擬環境中的Python來安裝它。如下:

最後且同樣重要的是,uwsgi配置裡應用屬性的值要設定成包含Flask應用的包的名稱。

相關文章