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 中讀取。

總結

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

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

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章