1. 程式人生 > >在 Docker 中完整部署 Web 應用

在 Docker 中完整部署 Web 應用

  ??

  作者簡介:外號夫子,長於長江之上「梨花島」,總喜歡一個江湖的傳說,如果你偶然記起關於「桃花島」黃藥師的傳說,記得划船來找我。個人部落格:fuzhii.com。其他博文《換個timeline看知乎》,《用機器學習的方法鑑別紅樓夢作者》。

  本文舉例的 Web 應用為 『top-topic-Zhihu』(換個 timeline 看知乎),抓取「知乎」網站每天新提出的熱門 top10 問題聚合顯示,提供另一種看知乎的姿勢,不被紛繁的 timeline 所迷惑。

  專案地址:https://github.com/Huangtuzhi/top-topic-Zhihu Dockerfile 和依賴檔案:

https://github.com/Huangtuzhi/docker-toptopic 雲服務商選擇『靈雀雲』提供容器服務:http://www.alauda.cn/ 映象地址:https://hub.alauda.cn/repos/huangtuzhi/docker-toptopicWeb頁面展示:http://toptopic-huangtuzhi.myalauda.cn:19991/ 『top-topic-Zhihu』應用結構

  需要這幾步來完成目標:

  “ 抓取——> 儲存資料持久化) ——> 分析——> 展示

  抓取:抓取部分主要是爬蟲,先手動輸入驗證碼獲取登入 Cookie。然後帶著該 Cookie 模擬發出 Get 請求來獲得網頁資料。思路是從自己的個人主頁開始爬,先爬出現在主頁 timeline 上的所有人,再爬這些人主頁上的其他人…,直到資料量足夠大。把人的 ID 儲存在 people 中。接著繼續爬 people 中所有人主頁上提出的問題,並獲得問題的關注人數和提問時間。把抓取到的問題儲存在 question 中。

  儲存:儲存可以把上面的 people,question 寫入文字或者 MySQL 資料庫。中間資料也應該放到資料庫中,不然記憶體會被無窮多的遞迴生成的中間資料填滿。本專案使用帶主鍵的 MySQL 表模擬記憶體 set 來儲存 people。

  分析:網站目的是獲取每天或者一個時間段內新提出的 top10 熱門問題,所以需要對時間過濾,對關注人數排序。這都可以在 SQL 查詢中完成。

  展示:展示包括後臺和前端兩部分,後臺需要在 DB 中取得資料構造成 JSON 格式以 CGI 的形式提供給前端呼叫。這裡使用 Python Flask 框架提供 CGI 後臺服務。前端頁面主要是跨域 AJax 請求後臺 CGI 來獲得資料,結合定義的模板來展示頁面。在版本 V1 中使用 AngularJS 來簡單的編寫模板及 AJax 請求的邏輯部分,在版本 V2 中使用 artTemplate 和封裝原生的 JS 來滿足需求。

  檔案目錄

  整個 Web 應用的目錄結構如下所示:

  

  Dockerfile

  Dockerfile 描述了容器的依賴和進行構建的步驟,下面會逐步解釋語句的含義。

  

  

  MySQL 安裝和配置

  MySQL 伺服器只需要用包管理器安裝 mysql-server-5.6,因為後臺使用 Python 作為伺服器語言,還需要安裝 MySQL 對 Python 語言的支援。需要使用 apt 安裝 python ,libmysqlclient-dev 和 python-dev,然後使用 pip 管理器安裝 MySQL-python。

  MySQL 的預設字符集為 latin1,而網頁顯示一般是 utf8 字符集,需要將 MySQL 的配置檔案的字符集置為 utf8。

  使用命令

  將本地已修改好的配置檔案覆蓋 Docker 中的 MySQL 配置檔案。檢視字符集

  

  若字符集如上所示,則說明已經修改成功。

  MySQL 的坑

  在上面的 Dockerfile 中看到分別給'root'@'127.0.0.1'和'root'@'localhost'都加了許可權,'root'@'localhost'的許可權在 SQL 語句最後才加上。這是因為

  使用'root'@'localhost'沒許可權建資料庫和表,報錯

  Access denied for user ‘root’@’localhost’ (using password: No)

  使用 'root'@'127.0.0.1'進入 Docker 後沒許可權連線 Mysql,報錯

  Access denied for user ‘root’@’localhost’ (using password: YES)

  於是這裡用'root'@'127.0.0.1'來建資料庫和表,最後再用'root'@'localhost'來連線資料庫。

  Nginx 安裝和配置

  Nginx 在這裡作為靜態頁面的伺服器,安裝只需要用 apt 管理器安裝即可。

  Nginx 需要配置 root 目錄來指定網站的檔案位置,把本地的 global.conf和nginx.conf檔案覆蓋到 Docker 中。

  在 global.conf 中我們指明伺服器根目錄為/usr/share/nginx/html/www

  

  在 Docker 中,我們將網站檔案放到新建的 /home/toptopic/web/www目錄。這裡建立一個軟連結將它們關聯起來,便於修改和維護。

  EXPOSE 兩個埠

  EXPOSE 在 Docker 中用來限制開放的埠。我們使用 Nginx 來提供靜態頁面訪問,使用 Flask 框架來提供動態頁面資料的獲取,所以需要開放兩個埠。

  查詢埠狀態,可以看到宿主機 2333 埠被對映到 Docker 的 2333 埠,宿主機 5000 埠被對映到 Docker 的 5000 埠。

  

  2223 埠與上節中的 Nginx 中設定的埠必須保持一致,因為 Nginx 使用 2223 埠提供服務,Docker 剛好必須把這個埠開放出去。

  在基於 Flask 框架寫的後臺服務 dataCGI.py 中,伺服器對應的監聽地址為

  host 必須設定為 0.0.0.0,表示監聽所有的 IP 地址。如果 host 使用 127.0.0.1,在容器外將無法訪問服務。同時,這裡的埠 5000 和 Dockerfile 中開放的另一個埠一致。

  啟動指令碼

  在 Dockerfile 中的 CMD 中可以指定 Docker 執行時執行一些命令。

  這三行分別啟動 MySQL,Nginx 和後臺服務。

  構建命令

  構建 Docker 容器

  執行容器

  需要注意的是若使用

  無法啟動 CMD 中的指令碼命令,這是因為在 docker run 後指定了 /bin/bash 後會覆蓋 CMD 中的命令。

  在雲平臺上部署

  在「靈雀雲」上部署一個 Docker 應用需要兩步:構建——建立服務。

  

  點選「構建」——「建立映象構建倉庫」,然後選擇 Github 倉庫源。需要把預先寫好的 Dockerfile 放在 Github中。

  

  構建好倉庫之後,點選「建立服務」。

  進行服務的設定,高階設定中服務地址型別選為 tcp-endpoint 即可(外部使用者可以直接通過 TCP 方式訪問這個服務地址,服務地址的埠是隨機分配的,一般會大於 10000 小於 65535)。

  最後點選最下方的「建立服務」完成部署。新建的服務如下所示: