1. 程式人生 > 程式設計 >Django搭建個人部落格:將專案部署到伺服器

Django搭建個人部落格:將專案部署到伺服器

我們的部落格雖然還有很多不完善的地方,但是沒關係,越早把它部署到網際網路上,才能越早發現線上特有的問題。現在也提倡漸進式開發,讓產品在迭代中快速成長。

部署考驗的不是你的 Django 程式設計水平,而是你對 Linux 的操作能力,以及對網路通訊的理解。多說無益,直接開幹!

配置伺服器

要架設網站,首先你要有一臺連線到網際網路的伺服器。國內比較出名的雲伺服器屬阿里雲騰訊雲百度雲,三家各有優劣,大家自行了解比較,並選擇自己適合的購買。

利益相關:博主自己用的是阿里雲,所以教程會以阿里雲ECS作為例子講解。新使用者通過推廣連結註冊有折扣和現金券(目前是20元);學生有優惠伺服器每月9.5元,效能還不錯,很划算。如果你想用其他雲伺服器,操作流程也差不多,不必擔心。

首先進入阿里雲ECS的購買頁面

圖片字很小,看不清楚的同學將就一下放大看吧。

挑重點說一下:

  • 例項從入門級裡選一款便宜的,以後流量高了再升級也不遲(土豪請無視這條)。
  • 映象選擇 Ubuntu 16.04 64位。其他 Linux 版本也是可以的。
  • 系統盤先選個 20G,夠你用一陣了。資料盤暫時用不上,不用勾選。

點選下一步,來到網路和安全組頁面:

這頁預設就行了,公網頻寬選最低的 1M ,初期夠用了。

點選下一步,到系統配置頁面:

為了後面遠端連線伺服器更簡單,這裡勾選自定義密碼,也就是輸入使用者/密碼的認證方式了。實際上祕鑰對的認證方式更安全些,以後摸熟了再改回來吧。

點選下一步,到分組設定

頁面。這個頁面全部預設設定就好了。點選下一步,確認訂單無誤後,就可以付款啦。

付款成功後,通過控制檯就可以看到已購買的雲伺服器了:

這裡有時候會有黃字提醒你伺服器的網路埠沒開,點選黃字連結去開通一下:

把 22(遠端連線埠)、443(HTTPS埠)、80(HTTP埠)都開啟,3389埠順便也開了。

至此伺服器的購買、配置就完成啦。稍等幾分鐘後等待初始化完成,就可以得到伺服器的公網 IP 地址,博主的是 118.31.35.48 ,後面會用到。

接下來就是正式的部署。

正式部署

開發時我們用的是 Django 自帶的開發伺服器,但那個效能太差了,不可能用到線上環境。所以線上部署時,我們不僅要安裝 Django

,還要安裝 NginxGunicorn,這三兄弟的工作流程如下:

  • 客戶端發來 http 請求,Nginx 作為直接對外的伺服器介面,對 http 請求進行分析
  • 如果是靜態資源請求,則由Nginx自己處理(效率極高)
  • 如果是動態資源請求,則把它轉發給 Gunicorn
  • Gunicorn 對請求進行預處理後,轉發給 Django,最終完成資源的返回

如果用餐館來做比喻的話,Nginx 就是迎賓小姐,客人如果點了酒水,迎賓小姐自己就幫忙拿了;而 Gunicorn 是傳菜員,Django 是廚師,他兩一起滿足客人對現炒美食的需求。

遠端連線

部署的第一步就是想辦法連線到雲伺服器上去,否則一切都免談。鑑於專案是在 Windows 環境開發的,推薦用 XShell 來作為遠端連線的工具,非常的好用。XShell 有學校及家庭版本,填一下姓名和郵箱就可以免費使用了。千萬別嫌麻煩去下載來路不明的“綠色版”、“純淨版”,萬一有木馬你哭都哭不出來了。

XShell 怎麼使用就不贅述了,以讀者的聰明才智,稍微查閱一下就明白了。

使用相當簡單,基本就是把主機 IP、埠號(22)以及登入驗證填好就能連線了。

連線成功後,就能在 XShell 視窗中看到阿里雲的歡迎字樣了:

Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-151-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

Welcome to Alibaba Cloud Elastic Compute Service !

root@dusaiphoto:~$ 
複製程式碼

root@dusaiphoto:~$是命令提示符,輸入命令時不需要你輸入這個。本文後面把 root@dusaiphoto:字元省略掉,方便大家閱讀。

程式碼部署

為了防止系統太舊引起的各種麻煩,先升級一下庫的版本:

~$ sudo apt-get update
~$ sudo apt-get upgrade
複製程式碼

完成之後,接著安裝需要的幾個包:

~$ sudo apt-get install nginx
~$ sudo apt-get install python3
~$ sudo apt-get install python3-pip
~$ sudo apt-get install git
~$ sudo pip3 install virtualenv
複製程式碼

分別安裝了 nginxpython3pipgitvirtualenv。其中 python3 和 pip3 的寫法是因為阿里雲自帶了 Python2.7,把它們區分一下。之前開發時虛擬環境用的 python 自帶的,為了避免讀者的版本不同造成的各類錯誤,穩妥起見用 virtualenv 庫來建立虛擬環境,操作步驟都是差不多的。

接下來就是要改一下 Django 的配置檔案 settings.py

my_blog/settings.py

# 關閉除錯模式
DEBUG = False

# 允許的伺服器
ALLOWED_HOSTS = ['*']

# 靜態檔案收集目錄
STATIC_ROOT = os.path.join(BASE_DIR,'collected_static')
複製程式碼
  • 部署時要關閉除錯模式,避免安全性問題(此時 Django 就不再處理靜態資源了)。
  • ALLOWED_HOSTS指明瞭允許訪問的伺服器名稱或 IP,星號表示允許所有的請求。實際部署時請改成你的域名或 IP,比如ALLOWED_HOSTS = ['.dusaiphoto.com','127.0.0.1']
  • 專案中有很多靜態檔案,部署時需要找一個地方統一收集起來,也就是STATIC_ROOT指定的地址了。

因為專案程式碼需要通過 GitHub 倉庫進行下載(就像本教程的示例程式碼一樣),因此修改完畢後需要把程式碼上傳到 GitHub。怎麼上傳這裡也不贅述了,博主之前寫過一篇《Win 10 連線 GitHub》的文章,有需要的讀者稍微讀一下。

需要注意的是,虛擬環境一般是需要在伺服器上重新生成的,因此我們需要把開發中用到的庫列一個清單,以便在伺服器上統一安裝。在本地虛擬環境中輸入:

pip freeze > requirements.txt
複製程式碼

專案中就多了個 requirements.txt 檔案,裡面記錄了專案需要的庫的清單。

教程為了演示,上傳了媒體資源和資料庫,實際開發時可千萬不要上傳。

然後更新 Git 記錄並上傳到 GitHub。重新回到伺服器的命令列,給專案程式碼建立目錄並進入此目錄:

~$ mkdir -p /home/sites/dusaiphoto.com
~$ cd /home/sites/dusaiphoto.com
複製程式碼

目錄位置是隨便你的,但建議找個地方統一管理所有的網站專案。

然後從 GitHub 中拉取專案程式碼:

../dusaiphoto.com$ git clone https://github.com/stacklens/django_blog_tutorial.git
複製程式碼

這裡拉取的部落格教程的程式碼。建議讀者先拉取教程程式碼來測試,成功之後再重新部署自己的程式碼。完成之後可以輸入 ls 指令,看看程式碼資料夾是否正常生成了。

接著在伺服器生成虛擬環境:

../dusaiphoto.com$ virtualenv --python=python3.5 env
../dusaiphoto.com$ source env/bin/activate
(env) ../dusaiphoto.com$ 
複製程式碼

這裡用 virtualenv 生成並激活了虛擬環境。python 版本選擇 3.5 還是 3.7 都可以,區別並不大。

接下來就是安裝庫、收集靜態資源、資料遷移了:

(env) ../dusaiphoto.com$ cd django_blog_tutorial
(env) ../django_blog_tutorial$ pip3 install -r requirements.txt
(env) ../django_blog_tutorial$ python3 manage.py collectstatic
(env) ../django_blog_tutorial$ python3 manage.py migrate
複製程式碼

程式碼部署基本就完成了,接下來配置 Nginx

Nginx

前面我們安裝了 Nginx ,先來試試安裝是否正常。啟動 nginx 服務:

(env) ~$ sudo service nginx start
複製程式碼

開啟瀏覽器,輸入你的伺服器公網 IP 地址

Nginx 歡迎介面出現了,神奇吧。但這個預設配置顯然是不能用的,所以需要重新寫 Nginx 的配置檔案。進入 /etc/nginx/sites-available 目錄,這裡是定義 Nginx 可用配置的地方。輸入指令 sudo vi dusaiphoto.com 建立配置檔案並開啟 vi 編輯器

(env) ~$ cd /etc/nginx/sites-available
(env) /etc/nginx/sites-available$ 
(env) /etc/nginx/sites-available$ sudo vi dusaiphoto.com
複製程式碼

關於 vi 編輯器如何使用也不贅述了,這裡只說兩個最基本的操作:

  • i 鍵切換到編輯模式,這時候才可以進行輸入、刪除、修改等操作
  • Ctrl + c 退回到命令模式,然後輸入 :wq + Enter 儲存檔案修改並退回到伺服器命令列

回到正題,用 vidusaiphoto.com 檔案中寫入:

server {
  charset utf-8;
  listen 80;
  server_name 118.31.35.48;  # 改成你的 IP

  location /static {
    alias /home/sites/dusaiphoto.com/django_blog_tutorial/collected_static;
  }
  
  location /media {
    alias /home/sites/dusaiphoto.com/django_blog_tutorial/media;
  }

  location / {
    proxy_set_header Host $host;
    proxy_pass http://unix:/tmp/118.31.35.48.socket;  # 改成你的 IP
  }
}
複製程式碼

此配置會監聽 80 埠(通常 http 請求的埠),監聽的 IP 地址寫你自己的伺服器公網 IP

配置中有3個規則:

  • 如果請求 static 路徑則由 Nginx 轉發到目錄中尋找靜態資源
  • 如果請求 media 路徑則由 Nginx 轉發到目錄中尋找媒體資源
  • 其他請求則交給 Django 處理

如果你已經申請好域名了,就把配置中有 IP 的地方都修改為域名,比如:server_name www.dusaiphoto.com;

寫好後就退出 vi 編輯器,回到命令列。因為我們寫的只是 Nginx 的可用配置,所以還需要把這個配置檔案連結到在用配置上去:

(env) ../sites-available$ sudo ln -s /etc/nginx/sites-available/dusaiphoto.com /etc/nginx/sites-enabled
複製程式碼

至此 Nginx 就配置好了,接下來搞定 Gunicorn

有的讀者無論怎麼配置都只能看到 Nginx 歡迎頁面,有可能是 sites-enabled 目錄中的 default 檔案覆蓋了你寫的配置。將 default 檔案刪掉就可以正常代理自己的配置檔案了。

Gunicorn及測試

先回到專案所在的目錄,並且進入虛擬環境,然後輸入:

(env) ../django_blog_tutorial$ pip3 install gunicorn
(env) ../django_blog_tutorial$ sudo service nginx reload
(env) ../django_blog_tutorial$ gunicorn --bind unix:/tmp/118.31.35.48.socket my_blog.wsgi:application
複製程式碼

這裡的三個步驟分別是:

  • 安裝 Gunicorn
  • 重啟 Nginx 服務
  • 啟動 Gunicorn

啟動 Gunicorn 也是一樣,如果你已經有域名了,就把套接字中的 IP 地址換成域名;wsgi 字眼前面是專案的名稱。另外 sudo service nginx reload 可替換成 sudo service nginx restart,區別是 reload 只過載配置檔案,restart 重啟整個服務。

接下來用瀏覽器訪問伺服器試一下:

大功告成啦,撒花慶祝!

後續工作

遺留問題

成功部署到線上後,還有些小問題沒解決。

第一個問題是進入文章詳情頁面, ckeditor 無法載入了,並且瀏覽器報出 prism_patched.js Not Found的錯誤。這個問題的根源在於之前我們在開發 ckeditor 的程式碼高亮功能時,prism 模組是直接插入到虛擬環境的庫中的,但問題是部署時虛擬環境是需要重新建立的,所以就缺少了這個 prism 外掛導致報錯。

解決辦法也很簡單,在虛擬環境中找到 prism 外掛的位置:

..\env\Lib\site-packages\ckeditor\static\ckeditor\ckeditor\plugins\prism
複製程式碼

然後把它原封不動的複製到專案的 static 中完全相同的目錄中去:

my_blog\static\ckeditor\ckeditor\plugins\prism
複製程式碼

這樣做行得通的原因是 django-ckeditor 也是一個 app,Django 訪問 app 資源時會優先在專案中搜索,沒有才去虛擬環境裡搜尋。

然後就是通過 GitHub 更新伺服器程式碼,並且重新收集靜態檔案:

(env) ../django_blog_tutorial$ git pull origin master
(env) ../django_blog_tutorial$ python3 manage.py collectstatic
複製程式碼

這個問題給我們的啟示就是:針對三方庫、資源的改動最好不要直接修改原始檔或環境,而是想辦法在專案副本中更改,這樣更便於維護。

有讀者發現舊的富文字評論中的表情沒顯示,這個別擔心,新發表的評論是沒問題的。

第二個問題是 GitHub 登入不正常了,這個多半不是程式碼的問題,而是你的伺服器以及 GitHub 的回撥配置問題。這裡也不展開講了,請讀者返回前面第三方登入的文章再研究下。

第三個問題是開發階段用的 sqlite 資料庫雖然很方便,但是效能較差。線上以效能為王,所以需要將資料庫更換為 MYSQL 這類主流的高效能資料庫。遠端安裝配置 MYSQL 的方法可以參考一下劉江的部落格,講得很清楚。

第四個問題是教程部署是以 root 使用者進行的,這是伺服器中具有最高許可權的使用者,除掉自身的瞎操作,一旦被攻擊者登入了會相當慘烈(尤其是使用者/密碼的登入方式,安全係數極低)。比較好的方式是重新建立一個普通使用者來進行部署,並且將登入方式改為祕鑰對。

後期運維

你的網站是需要不斷更新優化程式碼的。每次修改程式碼後,更新到伺服器上也很簡單。在虛擬環境中並進入專案目錄,依次(collectstatic 和 migrate 是可選的)執行以下命令:

git pull origin master
python3 manage.py collectstatic
python3 manage.py migrate
# 重啟 gunicorn
pkill gunicorn
gunicorn --bind unix:/tmp/118.31.35.48.socket my_blog.wsgi:application
複製程式碼

加上 cd 更改目錄的指令,部署過程有十幾條指令,手動輸入也太麻煩了。簡單粗暴的辦法是利用 XShell 的巨集,把部署指令寫成順序執行的指令碼,點幾個按鈕就完成了,非常方便。

更高階的做法是在伺服器上編寫自動化部署的指令碼,這個就讀者以後慢慢研究吧

如果你更改了 Nginx 的配置檔案,還需要重啟 Nginx 服務:

sudo service nginx reload
複製程式碼

最後,還記得前面章節開發的日誌記錄功能不?看看專案中有 logs 目錄嗎?

域名及優化

相對部署來說,域名配置就很容易了。阿里雲提供域名的購買、備案(頂級域名必須,約10個工作日)、解析服務,簡直全家桶有沒有。重點提醒有了域名之後要改的地方:

  • settings.py 中的 ALLOWED_HOSTS
  • Nginx 中與 IP/域名 有關的位置
  • Gunicorn 中與 IP/域名 有關的位置

域名搞定之後,接著就可以著手考慮把網站升級為 https 版本了,這是大趨勢,一定要做。(這個也留給讀者自己折騰)

另外,開發時為了效率把所有靜態資源都下載到本地,但是部署時不推薦這樣做,原因是靜態檔案通常體積都較大,你花血汗錢買的伺服器載入會很慢。儘量遠端 CDN 呼叫,像這樣:

<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
複製程式碼

國內推薦BootCDN,速度快還免費。

媒體資源也是類似,小圖還無所謂,大圖就要放在七牛雲這類的物件儲存雲上,否則你網頁的載入速度會很悲劇的。

最後再次提醒,在開發時我們往 settings.py 中寫入如 SECRET_KEY 、郵箱密碼等各種敏感資訊,部署時千萬不要直接上傳到網際網路(GitHub 庫是公開的!),而是把這些資訊寫到伺服器本地,然後在 settings.py 中讀取。

總結

部署可以說是入門者最大的難關了,也是檢驗成果、獲取成就感的關鍵一步。多查資料,要相信你遇到的問題別人早就遇到過了。

部署是菜鳥的畢業禮,也是新人的第一課。

路漫漫其修遠兮,吾將上下而求索。