Django初學(xué)者入門(mén)指南1-初識(shí)(譯&改)
Django初學(xué)者入門(mén)指南2-基礎(chǔ)知識(shí)(譯&改)
Django初學(xué)者入門(mén)指南3-高級(jí)概念(譯&改)
Django初學(xué)者入門(mén)指南4-登錄認(rèn)證(譯&改)
Django初學(xué)者入門(mén)指南5-存儲(chǔ)數(shù)據(jù)(譯&改)
Django初學(xué)者入門(mén)指南6-基于類(lèi)的頁(yè)面(譯&改)
Django初學(xué)者入門(mén)指南7-部署發(fā)布(譯&改)
簡(jiǎn)介
歡迎來(lái)到DJango入門(mén)教程系列的最后一部分痘拆!在本教程中嚷硫,我們將把DJango應(yīng)用程序部署到生產(chǎn)服務(wù)器上橱赠。同時(shí)還將為我們的服務(wù)器配置電子郵件服務(wù)和HTTPS證書(shū)责嚷。
最開(kāi)始我想給出一個(gè)使用虛擬專(zhuān)用服務(wù)器(VPS)的示例,它的應(yīng)用更加廣泛一點(diǎn)郭蕉。然后使用一個(gè)平臺(tái)服務(wù)泥畅,比如Heroku代承,但是它有太多細(xì)節(jié)需要處理龟梦。所以最終我選擇做一個(gè)主要使用VPS的教程隐锭。
我們的項(xiàng)目已經(jīng)上線啦!如果想在閱讀本教程之前在線體驗(yàn)一下计贰,可以直接訪問(wèn)我部署的網(wǎng)站:www.djangoboards.com钦睡。
代碼版本管理工具
版本控制是軟件開(kāi)發(fā)中一個(gè)極其重要的課題,尤其是在與團(tuán)隊(duì)一起工作并同時(shí)維護(hù)生產(chǎn)代碼躁倒、多個(gè)功能并行開(kāi)發(fā)時(shí)荞怒。無(wú)論是一個(gè)開(kāi)發(fā)人員項(xiàng)目還是多個(gè)開(kāi)發(fā)人員項(xiàng)目,每個(gè)項(xiàng)目都應(yīng)該進(jìn)行版本控制秧秉。
代碼版本管理工具有許多選擇褐桌,也許是因?yàn)?strong>GitHub的流行,Git在版本控制中成為了佼佼者象迎。因此荧嵌,如果你不熟悉版本控制,用Git就是一個(gè)很好的選擇砾淌。Git有許多教程啦撮、課程和資源,很容易找到需要的資料汪厨。
GitHub和Code School有一個(gè)關(guān)于Git的很好的交互式教程逻族,我在幾年前開(kāi)始從SVN轉(zhuǎn)到Git時(shí)就學(xué)習(xí)過(guò)這個(gè)教程,它做得很棒骄崩。
這是一個(gè)非常重要的注意事項(xiàng)聘鳞,本該從第一個(gè)教程開(kāi)始就強(qiáng)調(diào)它,不過(guò)因?yàn)楸鞠盗薪坛痰闹攸c(diǎn)是Django要拂,所以還是到這里才開(kāi)始講抠璃。如果這一切對(duì)你來(lái)說(shuō)都是陌生的,別擔(dān)心脱惰。一步一步來(lái)搏嗡。第一個(gè)項(xiàng)目不會(huì)是完美的,不斷學(xué)習(xí)和發(fā)展你的技能才是更重要的拉一,要持之以恒采盒。
Git它不僅僅是一個(gè)版本控制系統(tǒng),還有一個(gè)圍繞它構(gòu)建的工具和服務(wù)的豐富生態(tài)系統(tǒng)蔚润。比如說(shuō)持續(xù)集成磅氨、部署、代碼評(píng)審嫡纠、代碼質(zhì)量和項(xiàng)目管理等烦租。
使用Git支持Django項(xiàng)目的部署過(guò)程非常高效延赌。從源代碼庫(kù)中提取最新版本或在出現(xiàn)問(wèn)題時(shí)回滾到特定版本的都非常簡(jiǎn)單。還有許多服務(wù)與Git集成以便執(zhí)行自動(dòng)化測(cè)試和部署叉橱。
如果你的還沒(méi)有安裝Git挫以,請(qǐng)?jiān)谶@里下載https://git-scm.com/downloads。
配置Git
首先配置你的身份:
git config --global user.name "Vitor Freitas"
git config --global user.email vitor@simpleisbetterthancomplex.com
找到項(xiàng)目根目錄(manage.py
所在的目錄)窃祝,初始化一個(gè)Git本地倉(cāng)庫(kù):
git init
Initialized empty Git repository in /Users/vitorfs/Development/myproject/.git/
檢查一下代碼倉(cāng)庫(kù)的狀態(tài):
git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
accounts/
boards/
manage.py
myproject/
requirements.txt
static/
templates/
nothing added to commit but untracked files present (use "git add" to track)
在繼續(xù)添加源代碼文件之前掐松,請(qǐng)?jiān)陧?xiàng)目根目錄中創(chuàng)建一個(gè).gitignore
的新文件,這個(gè)新文件將幫助我們過(guò)濾代碼倉(cāng)庫(kù)管理的文件粪小,忽略諸如緩存文件甩栈、日志文件等不需要進(jìn)行管理的非必要文件。
你可以從GitHub上獲取Python項(xiàng)目的常用.gitignore
文件糕再,這里。
確認(rèn)文件的名稱(chēng)一定要是.gitignore
玉转,而不是Python.gitignore
之類(lèi)的突想。
舉個(gè)例子,你可以在.gitignore
里添加對(duì)SQLite數(shù)據(jù)庫(kù)文件的過(guò)濾:
.gitignore
__pycache__/
*.py[cod]
.env
venv/
# SQLite database files
*.sqlite3
好了究抓,現(xiàn)在我們將項(xiàng)目的文件添加到Git本地倉(cāng)庫(kù):
git add .
注意這里的.
猾担,這個(gè)命令的意思是將這個(gè)目錄下的所有未添加到Git倉(cāng)庫(kù)里的文件(不包括被.gitignore
忽略的文件),添加到倉(cāng)庫(kù)里刺下。
然后提交一次代碼:
git commit -m "Initial commit"
養(yǎng)成一個(gè)好習(xí)慣绑嘹,每次提交的時(shí)候都添加備注,簡(jiǎn)要說(shuō)明這次提交的內(nèi)容橘茉。
遠(yuǎn)程倉(cāng)庫(kù)
現(xiàn)在讓我們使用GitHub來(lái)配置這個(gè)項(xiàng)目的一個(gè)遠(yuǎn)程倉(cāng)庫(kù)把工腋。第一步,在GitHub上創(chuàng)建一個(gè)賬號(hào)畅卓,確認(rèn)你的郵件地址擅腰。然后你就可以創(chuàng)建GitHub倉(cāng)庫(kù)了。
然后我們需要為倉(cāng)庫(kù)命名翁潘,其他的選項(xiàng)(README、.gitignore拜马、license)都暫時(shí)不要勾選或添加渗勘,確保項(xiàng)目是一個(gè)空項(xiàng)目:
在你建好項(xiàng)目后應(yīng)該看見(jiàn)下面的頁(yè)面:
在本地開(kāi)始配置吧,運(yùn)行下面的命令:
git remote add origin git@github.com:sibtc/django-boards.git
執(zhí)行push命令把本地代碼推到遠(yuǎn)程倉(cāng)庫(kù):
git push origin master
Counting objects: 84, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (81/81), done.
Writing objects: 100% (84/84), 319.70 KiB | 0 bytes/s, done.
Total 84 (delta 10), reused 0 (delta 0)
remote: Resolving deltas: 100% (10/10), done.
To git@github.com:sibtc/django-boards.git
* [new branch] master -> master
這里創(chuàng)建的代碼倉(cāng)庫(kù)只是為了演示如何給現(xiàn)有的項(xiàng)目添加Git代碼倉(cāng)庫(kù)以及添加遠(yuǎn)程倉(cāng)庫(kù)俩莽,實(shí)際上這個(gè)項(xiàng)目的官方遠(yuǎn)程倉(cāng)庫(kù)是:https://github.com/sibtc/django-beginners-guide.
項(xiàng)目配置
不管代碼是保存在一個(gè)公開(kāi)或私有的遠(yuǎn)程倉(cāng)庫(kù)旺坠,那些敏感信息都不應(yīng)該被提交到遠(yuǎn)程倉(cāng)庫(kù)里,例如密鑰扮超、密碼价淌、API密鑰等申眼。
基于這個(gè)原則,我們需要對(duì)settings.py
里特定的兩類(lèi)信息進(jìn)行處理:
- 諸如密碼蝉衣、秘鑰之類(lèi)的敏感信息括尸;
- 特定環(huán)境使用的配置信息.
密碼和密鑰可以使用本地文件或環(huán)境變量進(jìn)行存儲(chǔ),不要提交到遠(yuǎn)程倉(cāng)庫(kù):
# 環(huán)境變量
import os
SECRET_KEY = os.environ['SECRET_KEY']
# 或本地文件
with open('/etc/secret_key.txt') as f:
SECRET_KEY = f.read().strip()
這里推薦一個(gè)強(qiáng)大的工具庫(kù)Python Decouple病毡,我每一個(gè)DJango項(xiàng)目開(kāi)發(fā)中都會(huì)用它濒翻。它可以自動(dòng)檢索名為.env
本地文件來(lái)關(guān)聯(lián)配置的變量,進(jìn)行設(shè)置和讀取啦膜。同時(shí)它也提供接口來(lái)定義默認(rèn)值有送,并在可能的條件下將數(shù)據(jù)轉(zhuǎn)換為int、bool和list等類(lèi)型僧家。
這個(gè)不是必須的雀摘,但是我強(qiáng)烈建議使用它。
執(zhí)行下面的命令安裝一下:
pip install python-decouple
myproject/settings.py
from decouple import config
SECRET_KEY = config('SECRET_KEY')
然后把敏感信息抽取出來(lái)八拱,放到項(xiàng)目根目錄與manage.py
同級(jí)的一個(gè)新文件.env
里阵赠,注意這里也是以點(diǎn)開(kāi)頭的文件名:
myproject/
|-- myproject/
| |-- accounts/
| |-- boards/
| |-- myproject/
| |-- static/
| |-- templates/
| |-- .env <-- 這里!
| |-- .gitignore
| |-- db.sqlite3
| +-- manage.py
+-- venv/
.env
SECRET_KEY=rqr_cjv4igscyu8&&(0ce(=sy=f2)p=f_wn&@0xsp7m$@!kp=d
.env
在.gitignore
中已經(jīng)被配置為了忽略,所以每當(dāng)需要部署應(yīng)用程序或者在新的設(shè)備上運(yùn)行這個(gè)項(xiàng)目時(shí)肌稻,我們都需要新建一個(gè).env
文件并添加必要的配置變量清蚀。
讓我們?cè)侔惭b一個(gè)三方庫(kù)來(lái)幫助我們進(jìn)行數(shù)據(jù)庫(kù)的配置。它讓我們可以通過(guò)一行文本就實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)連接的配置:
pip install dj-database-url
現(xiàn)在我們需要解耦所有的配置:
myproject/settings.py
from decouple import config, Csv
import dj_database_url
SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())
DATABASES = {
'default': dj_database_url.config(
default=config('DATABASE_URL')
)
}
下面是我們本地設(shè)備的一個(gè)示例配置文件.env
:
SECRET_KEY=rqr_cjv4igscyu8&&(0ce(=sy=f2)p=f_wn&@0xsp7m$@!kp=d
DEBUG=True
ALLOWED_HOSTS=.localhost,127.0.0.1
注意這里DEBUG
配置項(xiàng)設(shè)了一個(gè)默認(rèn)值爹谭,當(dāng)部署到生產(chǎn)環(huán)境時(shí)枷邪,只需要忽略去配置這一項(xiàng)就可以了,它會(huì)默認(rèn)為False
诺凡。
這里ALLOWED_HOSTS
將會(huì)被轉(zhuǎn)換成一個(gè)類(lèi)似['.localhost', '127.0.0.1'. ]
的列表东揣,這是本地設(shè)備的配置,如果是生產(chǎn)設(shè)備腹泌,它應(yīng)該是['.djangoboards.com', ]
這樣的或者其他你所擁有的域名救斑。
這個(gè)配置可以保證你的應(yīng)用程序只在這個(gè)域名下提供服務(wù)。
項(xiàng)目依賴(lài)跟蹤
持續(xù)保持跟蹤項(xiàng)目的依賴(lài)配置是一個(gè)好習(xí)慣真屯,這樣可以更方便地將項(xiàng)目部署到其他設(shè)備上脸候。
我們可以通過(guò)下面的命令檢查現(xiàn)在安裝的依賴(lài)庫(kù):
pip freeze
dj-database-url==0.4.2
Django==1.11.6
django-widget-tweaks==1.4.1
Markdown==2.6.9
python-decouple==3.1
pytz==2017.2
創(chuàng)建一個(gè)名為requirements.txt
的文件放到項(xiàng)目根目錄,將項(xiàng)目的依賴(lài)拷貝到這里:
requirements.txt
dj-database-url==0.4.2
Django==1.11.6
django-widget-tweaks==1.4.1
Markdown==2.6.9
python-decouple==3.1
這里剔除了pytz==2017.2
绑蔫,因?yàn)檫@個(gè)是由DJango自動(dòng)安裝的运沦。
將文件添加到Git倉(cāng)庫(kù)并推送到遠(yuǎn)程倉(cāng)庫(kù):
git add .
git commit -m "Add requirements.txt file"
git push origin master
域名
需要申請(qǐng)一個(gè)域名來(lái)部署DJango應(yīng)用程序,這樣我們才能配置電子郵件服務(wù)和https證書(shū)配深。
這里我注冊(cè)了域名www.DjangoBoards.com携添。
部署策略
下面是本教程中將使用的部署策略的架構(gòu)設(shè)計(jì):
云服務(wù)是使用的Digital Ocean的VPS,這里根據(jù)大家實(shí)際情況自行注冊(cè)篓叶。
首先會(huì)有一個(gè)NGINX烈掠,插圖使用的是一個(gè)獸人羞秤。NGINX會(huì)首先接收到所有的請(qǐng)求,但它不會(huì)對(duì)這些請(qǐng)求數(shù)據(jù)做復(fù)雜的處理左敌。除非請(qǐng)求的數(shù)據(jù)是它自己能提供的服務(wù)如簡(jiǎn)單的獲取靜態(tài)資源瘾蛋,其他的請(qǐng)求它就直接傳遞給Gunicorn。
NGINX還將配置HTTPS證書(shū)矫限,這樣就只接收HTTPS請(qǐng)求哺哼,如果客戶端嘗試通過(guò)HTTP訪問(wèn)服務(wù),NGINX可以重定位到HTTPS服務(wù)叼风,然后再對(duì)請(qǐng)求進(jìn)行處理取董。
我們也會(huì)安裝一個(gè)certbot來(lái)自動(dòng)更新Let’s Encrypt的證書(shū)。
Gunicorn是一個(gè)應(yīng)用服務(wù)器无宿,根據(jù)服務(wù)器的處理能力(處理器數(shù)量)茵汰,它能生成多個(gè)worker提供并行處理多任務(wù)的能力,同時(shí)它還能管理工作負(fù)載孽鸡,和執(zhí)行Python以及DJango代碼蹂午。
DJango承擔(dān)著最多的工作,它需要訪問(wèn)數(shù)據(jù)庫(kù)(如PostgreSQL)和文件系統(tǒng)梭灿,大多數(shù)的工作都集中在頁(yè)面里,渲染模板冰悠,所有在我們之前教程里的工作堡妒。當(dāng)DJango處理完請(qǐng)求后,它會(huì)返回處理結(jié)果給Gunicorn溉卓,再傳遞給NGINX皮迟,最終再傳回用戶客戶端。
還需要安裝PostgreSQL桑寨,一個(gè)生產(chǎn)級(jí)別的數(shù)據(jù)庫(kù)系統(tǒng)伏尼,通過(guò)DJango的ORM系統(tǒng),我們可以很簡(jiǎn)單的進(jìn)行數(shù)據(jù)庫(kù)切換尉尾。
最后一步是安裝Supervisor爆阶,這是一個(gè)過(guò)程監(jiān)控系統(tǒng),它會(huì)全程監(jiān)控Gunicorn和Django來(lái)保證服務(wù)的正常運(yùn)行沙咏。如果服務(wù)器重啟了辨图,或者Gunicorn異常退出了,Supervisor都會(huì)將自動(dòng)重啟故障的服務(wù)肢藐。
部署VPS (Digital Ocean)
你可以使用任何其他服務(wù)提供的VPS故河,配置方式應(yīng)該是類(lèi)似的,這里我們的服務(wù)器使用Ubuntu 16.04操作系統(tǒng)吆豹。
首先讓我們創(chuàng)建一個(gè)新服務(wù)器(Digital Ocean里被稱(chēng)為Droplet
)鱼的,選擇操作系統(tǒng)Ubuntu 16.04:
選擇服務(wù)器配置理盆,這里最低配置就可以了:
輸入一個(gè)主機(jī)名,這里我輸入的是django-boards
:
如果你有SSH秘鑰凑阶,你可以直接添加到你的賬戶里猿规,這樣你就可以直接使用秘鑰進(jìn)行登錄。如果沒(méi)有就只能通過(guò)郵箱獲取登錄根密碼晌砾。
選擇一下服務(wù)器的IP地址:
在登錄進(jìn)這個(gè)服務(wù)器前坎拐,將我們的域名指向這個(gè)IP地址,因?yàn)镈NS配置需要一點(diǎn)時(shí)間养匈,所以我們可以同步進(jìn)行哼勇。
這里我們添加了兩個(gè)A records
,一個(gè)指向域名djangoboards.com
呕乎,另一個(gè)指向www.djangoboards.com
积担,接下啦我們會(huì)用NGINX配置一個(gè)規(guī)范的URL。
好了猬仁,讓我們?cè)诮K端上登錄服務(wù)器吧:
ssh root@45.55.144.54
root@45.55.144.54's password:
登錄成功后你會(huì)看到下面的消息:
You are required to change your password immediately (root enforced)
Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-93-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud
0 packages can be updated.
0 updates are security updates.
Last login: Sun Oct 15 18:39:21 2017 from 82.128.188.51
Changing password for root.
(current) UNIX password:
重新設(shè)置登錄密碼帝璧,然后開(kāi)始配置服務(wù)器吧。
sudo apt-get update
sudo apt-get -y upgrade
如果在升級(jí)中出現(xiàn)任何提示湿刽,選擇keep the local version currently installed
的烁。
Python 3.6
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get update
sudo apt-get install python3.6
PostgreSQL
sudo apt-get -y install postgresql postgresql-contrib
NGINX
sudo apt-get -y install nginx
Supervisor
sudo apt-get -y install supervisor
sudo systemctl enable supervisor
sudo systemctl start supervisor
Virtualenv
wget https://bootstrap.pypa.io/get-pip.py
sudo python3.6 get-pip.py
sudo pip3.6 install virtualenv
為應(yīng)用程序創(chuàng)建用戶
使用下面的命令創(chuàng)建新用戶:
adduser boards
一般來(lái)說(shuō),我會(huì)選擇使用應(yīng)用程序的名稱(chēng)诈闺,這樣可以將每個(gè)應(yīng)用程序的用戶權(quán)限獨(dú)立開(kāi)渴庆。
將這個(gè)新用戶添加到sudoers列表:
gpasswd -a boards sudo
PostgreSQL 數(shù)據(jù)庫(kù)配置
首先切換到postgres用戶:
sudo su - postgres
創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)用戶:
createuser u_boards
創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)文件并將這個(gè)用戶設(shè)為owner
:
createdb django_boards --owner u_boards
為用戶定義一個(gè)安全的密碼:
psql -c "ALTER USER u_boards WITH PASSWORD 'BcAZoYWsJbvE7RMgBPzxOCexPRVAq'"
退出postgres用戶:
exit
DJango項(xiàng)目配置
切換到應(yīng)用程序用戶:
sudo su - boards
首先我們看看當(dāng)前目錄:
pwd
/home/boards
首先將項(xiàng)目代碼從遠(yuǎn)程倉(cāng)庫(kù)clone下來(lái):
git clone https://github.com/sibtc/django-beginners-guide.git
創(chuàng)建一個(gè)虛擬環(huán)境:
virtualenv venv -p python3.6
初始化并啟用虛擬環(huán)境:
source venv/bin/activate
安裝依賴(lài):
pip install -r django-beginners-guide/requirements.txt
這里需要安裝兩個(gè)額外的庫(kù):Gunicorn和PostgreSQL驅(qū)動(dòng):
pip install gunicorn
pip install psycopg2
在/home/boards/django-beginners-guide目錄下,創(chuàng)建一個(gè).env文件來(lái)存儲(chǔ)數(shù)據(jù)庫(kù)的秘鑰雅镊、證書(shū)和其他配置:
/home/boards/django-beginners-guide/.env
SECRET_KEY=rqr_cjv4igscyu8&&(0ce(=sy=f2)p=f_wn&@0xsp7m$@!kp=d
ALLOWED_HOSTS=.djangoboards.com
DATABASE_URL=postgres://u_boards:BcAZoYWsJbvE7RMgBPzxOCexPRVAq@localhost:5432/django_boards
數(shù)據(jù)庫(kù)URL的語(yǔ)法是:postgres://db_user
:db_password
@db_host
:db_port
/db_name
.
接下來(lái)讓我們遷移數(shù)據(jù)庫(kù)襟雷、處理靜態(tài)文件并創(chuàng)建一個(gè)超級(jí)用戶:
cd django-beginners-guide
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, boards, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying boards.0001_initial... OK
Applying boards.0002_auto_20170917_1618... OK
Applying boards.0003_topic_views... OK
Applying sessions.0001_initial... OK
再處理靜態(tài)文件:
python manage.py collectstatic
Copying '/home/boards/django-beginners-guide/static/js/jquery-3.2.1.min.js'
Copying '/home/boards/django-beginners-guide/static/js/popper.min.js'
Copying '/home/boards/django-beginners-guide/static/js/bootstrap.min.js'
Copying '/home/boards/django-beginners-guide/static/js/simplemde.min.js'
Copying '/home/boards/django-beginners-guide/static/css/app.css'
Copying '/home/boards/django-beginners-guide/static/css/bootstrap.min.css'
Copying '/home/boards/django-beginners-guide/static/css/accounts.css'
Copying '/home/boards/django-beginners-guide/static/css/simplemde.min.css'
Copying '/home/boards/django-beginners-guide/static/img/avatar.svg'
Copying '/home/boards/django-beginners-guide/static/img/shattered.png'
...
這個(gè)命令會(huì)將所有靜態(tài)文件拷貝到一個(gè)外部目錄讓NGINX為用戶提供服務(wù)。稍后會(huì)提到仁烹。
為應(yīng)用程序創(chuàng)建一個(gè)超級(jí)用戶:
python manage.py createsuperuser
Gunicorn配置
Gunicorn在代理服務(wù)器后面負(fù)責(zé)執(zhí)行DJango代碼耸弄。
在/home/boards
下創(chuàng)建一個(gè)新文件命名為gunicorn_start
:
#!/bin/bash
NAME="django_boards"
DIR=/home/boards/django-beginners-guide
USER=boards
GROUP=boards
WORKERS=3
BIND=unix:/home/boards/run/gunicorn.sock
DJANGO_SETTINGS_MODULE=myproject.settings
DJANGO_WSGI_MODULE=myproject.wsgi
LOG_LEVEL=error
cd $DIR
source ../venv/bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DIR:$PYTHONPATH
exec ../venv/bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $WORKERS \
--user=$USER \
--group=$GROUP \
--bind=$BIND \
--log-level=$LOG_LEVEL \
--log-file=-
這個(gè)腳本會(huì)啟動(dòng)應(yīng)用服務(wù)器,配置提供了諸如DJango項(xiàng)目所在位置卓缰、使用哪個(gè)應(yīng)用程序用戶啟動(dòng)服務(wù)器等信息口渔。
讓這個(gè)文件可以被運(yùn)行:
chmod u+x gunicorn_start
創(chuàng)建兩個(gè)空文件夾玉工,一個(gè)用來(lái)存儲(chǔ)socket
文件,一個(gè)用來(lái)存儲(chǔ)日志文件:
mkdir run logs
現(xiàn)在我們的/home/boards
目錄應(yīng)該是這個(gè)樣子的:
django-beginners-guide/
gunicorn_start
logs/
run/
staticfiles/
venv/
staticfiles
是由collectstatic
命令創(chuàng)建的。
配置Supervisor
首先在/home/boards/logs/
下創(chuàng)建一個(gè)空的log文件:
touch logs/gunicorn.log
創(chuàng)建一個(gè)新的supervisor
文件:
sudo vim /etc/supervisor/conf.d/boards.conf
[program:boards]
command=/home/boards/gunicorn_start
user=boards
autostart=true
autorestart=true
redirect_stderr=true
stdout_logfile=/home/boards/logs/gunicorn.log
保存文件并運(yùn)行下面的命令:
sudo supervisorctl reread
sudo supervisorctl update
檢查一下現(xiàn)在的狀態(tài):
sudo supervisorctl status boards
boards RUNNING pid 308, uptime 0:00:07
配置 NGINX
下一步是配置NGINX服務(wù)器知举,關(guān)聯(lián)靜態(tài)文件至朗,和將請(qǐng)求傳遞給Gunicorn:
在/etc/nginx/sites-available/
目錄下添加一個(gè)新的配置文件命名為boards
:
upstream app_server {
server unix:/home/boards/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name www.djangoboards.com; # here can also be the IP address of the server
keepalive_timeout 5;
client_max_body_size 4G;
access_log /home/boards/logs/nginx-access.log;
error_log /home/boards/logs/nginx-error.log;
location /static/ {
alias /home/boards/staticfiles/;
}
# checks for static file, if not found proxy to app
location / {
try_files $uri @proxy_to_app;
}
location @proxy_to_app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
創(chuàng)建一個(gè)符號(hào)鏈接(symbolic link)到sites-enabled
文件夾:
sudo ln -s /etc/nginx/sites-available/boards /etc/nginx/sites-enabled/boards
移除默認(rèn)的NGINX網(wǎng)站:
sudo rm /etc/nginx/sites-enabled/default
重啟NGINX服務(wù):
sudo service nginx restart
如果此時(shí)DNS配置已經(jīng)更新孕讳,那么www.djangoboards.com應(yīng)該已經(jīng)可以訪問(wèn)了奇徒。
配置電子郵件服務(wù)
最開(kāi)始建議使用Mailgun,它提供可靠的免費(fèi)服務(wù)計(jì)劃偿乖,每月可發(fā)送12,000次击罪。
注冊(cè)一個(gè)免費(fèi)賬號(hào)哲嘲,按照步驟填寫(xiě)信息就可以了,非常簡(jiǎn)單媳禁。這個(gè)需要和你的域名同時(shí)使用眠副,這個(gè)教程里就是Namecheap。
點(diǎn)擊添加域名
按鈕添加一個(gè)新的域名竣稽,根據(jù)提示進(jìn)行操作囱怕,需要保證使用"mg."的子域名:
從下圖的位置獲取DNS的記錄:
使用服務(wù)商提供的web頁(yè)面,將它添加到你的域名下毫别。
Add it to your domain, using the web interface offered by your registrar:
對(duì)MX也做童謠的操作:
將它們也添加到你的域名下:
這一步不是強(qiáng)制的娃弓,既然我們已經(jīng)到這里了,就也把它確認(rèn)一下吧:
在我們添加完DNS記錄后岛宦,點(diǎn)擊Check DNS Records Now:
這里需要一點(diǎn)耐心台丛,可能需要多花一點(diǎn)時(shí)間來(lái)驗(yàn)證DNS配置是否生效。
我們可以先配置應(yīng)用程序接收的連接參數(shù)砾肺。
myproject/settings.py
EMAIL_BACKEND = config('EMAIL_BACKEND', default='django.core.mail.backends.smtp.EmailBackend')
EMAIL_HOST = config('EMAIL_HOST', default='')
EMAIL_PORT = config('EMAIL_PORT', default=587, cast=int)
EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='')
EMAIL_USE_TLS = config('EMAIL_USE_TLS', default=True, cast=bool)
DEFAULT_FROM_EMAIL = 'Django Boards <noreply@djangoboards.com>'
EMAIL_SUBJECT_PREFIX = '[Django Boards] '
本地設(shè)備的.env文件應(yīng)該是下面這樣:
SECRET_KEY=rqr_cjv4igscyu8&&(0ce(=sy=f2)p=f_wn&@0xsp7m$@!kp=d
DEBUG=True
ALLOWED_HOSTS=.localhost,127.0.0.1
DATABASE_URL=sqlite:///db.sqlite3
EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend
而生產(chǎn)環(huán)境的.env文件應(yīng)該是下面這樣:
SECRET_KEY=rqr_cjv4igscyu8&&(0ce(=sy=f2)p=f_wn&@0xsp7m$@!kp=d
ALLOWED_HOSTS=.djangoboards.com
DATABASE_URL=postgres://u_boards:BcAZoYWsJbvE7RMgBPzxOCexPRVAq@localhost:5432/django_boards
EMAIL_HOST=smtp.mailgun.org
EMAIL_HOST_USER=postmaster@mg.djangoboards.com
EMAIL_HOST_PASSWORD=ED2vmrnGTM1Rdwlhazyhxxcd0F
你可以在Mailgun上的Domain Information分段找到證書(shū)相關(guān)的信息挽霉。
-
EMAIL_HOST
: SMTP 主機(jī)名 -
EMAIL_HOST_USER
: 默認(rèn) SMTP 登錄賬戶 -
EMAIL_HOST_PASSWORD
: 默認(rèn) 密碼
我們可以測(cè)試一下生產(chǎn)服務(wù)器的新配置。將本地設(shè)備的配置文件settings.py修改一下变汪,提交的遠(yuǎn)程倉(cāng)庫(kù)侠坎。再在服務(wù)器上拉取新代碼并重啟Gunicorn:
git pull
編輯.env的電子郵件服務(wù)證書(shū)。
重啟Gunicorn:
sudo supervisorctl restart boards
現(xiàn)在我們可以嘗試訪問(wèn)密碼重置流程:
在Mailgun的dashboard上你可以查看一些郵件發(fā)送的統(tǒng)計(jì)信息:
配置 HTTPS 證書(shū)
現(xiàn)在讓我們給應(yīng)用程序配置一個(gè)HTTPS證書(shū)裙盾,這里選擇使用Let’s Encrypt实胸。
原來(lái)配置HTTPS沒(méi)有這么簡(jiǎn)單過(guò),甚至現(xiàn)在可以免費(fèi)使用它闷煤,他們提供了一個(gè)自動(dòng)安裝和刷新證書(shū)的解決方案certbot童芹,使用起來(lái)非常簡(jiǎn)單:
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
現(xiàn)在安裝證書(shū):
sudo certbot --nginx
只需要跟著提示填寫(xiě)涮瞻,當(dāng)被問(wèn)到:
Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
選擇2
就會(huì)將所有的HTTP請(qǐng)求重定位為HTTPS請(qǐng)求鲤拿。
這樣就可以保證所有請(qǐng)求都是通過(guò)HTTPS來(lái)進(jìn)行的:
修改配置為自動(dòng)更新證書(shū),執(zhí)行下面的命令來(lái)編輯crontab
文件:
sudo crontab -e
在文件最后添加下面的這一行代碼:
0 4 * * * /usr/bin/certbot renew --quiet
這個(gè)命令會(huì)在每天的凌晨4點(diǎn)啟動(dòng)任務(wù)署咽,更新30天內(nèi)到期的證書(shū)近顷。
小結(jié)
非常感謝所有關(guān)注本系列教程的人給予的評(píng)論和反饋,我真的很感激宁否!這是本系列的最后一個(gè)教程窒升。希望你喜歡!
盡管這是本系列教程的最后一部分慕匠,但我計(jì)劃編寫(xiě)一些后續(xù)教程饱须,探索其他有趣的主題,例如數(shù)據(jù)庫(kù)優(yōu)化和在當(dāng)前已有的基礎(chǔ)上添加更多功能台谊。
順便說(shuō)一句蓉媳,如果你對(duì)這個(gè)項(xiàng)目感興趣譬挚,項(xiàng)目的源代碼可在GitHub上找到:https://github.com/sibtc/django-beginners-guide/
請(qǐng)告訴我你還想看到什么樣的教程!:-)