Diango博客--11.Nginx + Gunicorn + Supervisor 方式部署
文章目錄
- 0.部署前準(zhǔn)備
- 1.創(chuàng)建一個(gè)超級(jí)用戶
- 2.更新 SQLite3
- 3.安裝 Python3 、pip3.6以及 Pipenv
- 4.部署代碼
- 5.使用 Gunicorn
- 6.啟動(dòng) Nginx 服務(wù)器
- 7.配置 Nginx
- 8.關(guān)閉 DEBUG 模式,收集靜態(tài)文件
- 9.使用 Supervisor管理 Gunicorn 進(jìn)程
- 10.使用 CDN 加快 Bootstrap 和 jQuery 的加載速度
0.部署前準(zhǔn)備
1)使用比較流行的 Nginx + Gunicorn 的方式將 django 開發(fā)的博客部署到自己的服務(wù)器,讓別人能夠通過(guò)域名訪問(wèn)博客。
2)開發(fā)使用的本地環(huán)境為 Windows 10,服務(wù)器環(huán)境為 CentOS 7(64 位)
3)輔助工具 Xshell
1.創(chuàng)建一個(gè)超級(jí)用戶
adduser fxd
passwd fxd
usermod -aG wheel fxd
su - fxd
新用戶創(chuàng)建并切換成功了。如果是新服務(wù)器的話,最好先更新一下系統(tǒng),避免因?yàn)榘姹咎f而給后面安裝軟件帶來(lái)麻煩。運(yùn)行下面的兩條命令:
sudo yum update
sudo yum upgrade
2.更新 SQLite3
為了方便,我們博客使用了 SQLite3 數(shù)據(jù)庫(kù),django 2.2 要求 SQLite3 數(shù)據(jù)庫(kù)版本在 3.8.3 以上,而 CentOS 7 系統(tǒng)自帶版本低于 django 2.2 所要求的最低版本,所以首先來(lái)更新 SQLite3 的版本。
注意:有可能你使用的服務(wù)器系統(tǒng)發(fā)行版 SQLite3 已經(jīng)高于 3.8.3,這一步就可以跳過(guò)。請(qǐng)執(zhí)行 sqlite3 --version 查看 SQLite3 的版本
首先登陸到 sqlite 的官方下載地址,查看最新發(fā)布的版本,本教程使用版本為 3.29.0,找到該版本的源碼壓縮包,復(fù)制其下載鏈接,然后通過(guò) wget 命令下載到服務(wù)器(一般將源碼放在 ~/src 目錄下。)
mkdir -p ~/src
cd ~/src
下載 sqlite3 源碼并解壓安裝
wget https://sqlite.org/2019/sqlite-autoconf-3290000.tar.gz
tar zxvf sqlite-autoconf-3290000.tar.gz
cd sqlite-autoconf-3290000
./configure
make
sudo make install
注意:如果 wget 命令不存在,使用 sudo yum install -y wget 安裝即可。
報(bào)錯(cuò):./configure報(bào)錯(cuò)
解決方法:sudo yum install -y gcc glibc
之后執(zhí)行 ./configure
查看sqlite3版本:
Xshell中重新打開一個(gè)終端:
sqlite3 --version
3.安裝 Python3 、pip3.6以及 Pipenv
CentOS 7 自帶的 Python 發(fā)行版為 2.7,因此需要安裝 Python3,為了兼容性,我們安裝 Python 3.6.4。
首先安裝可能的依賴:
sudo yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel
然后下載 Python 3.6.4 的源碼并解壓:
cd ~/src
wget https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz
tar -zxvf Python-3.6.4.tgz
最后編譯安裝:
cd Python-3.6.4
./configure LD_RUN_PATH=/usr/local/lib LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include"
make LD_RUN_PATH=/usr/local/lib
sudo make install
注意這里安裝 Python 時(shí),Python 會(huì)依賴 SQLite3 的庫(kù),所以在 configure 時(shí)通過(guò) LD_RUN_PATH 指定依賴的搜索目錄(因?yàn)槲覀冎案铝?SQLite3 的版本,指定依賴搜索目錄確保使用新的 SQLite3 依賴庫(kù)),另外兩個(gè)參數(shù)作用類似。
然后輸入 python3.6 -V 和 pip3.6 -V 命令測(cè)試安裝結(jié)果,輸出版本號(hào)說(shuō)明安裝成功了。
有了 pip,就可以安裝 Pipenv 了:
首先建立軟連接:
sudo ln -s /usr/local/bin/pip3.6 /usr/bin/pip3.6
sudo ln -s /usr/local/bin/pip3 /usr/bin/pip3
然后安裝:
sudo pip3.6 install pipenv
注意:
python2.7和python3.6的區(qū)別
pip2.7和pip3.6的區(qū)別
以下部分列出兩種指令的輸出情況,供參考:
4.部署代碼
1)首先要對(duì)項(xiàng)目做一點(diǎn)配置,打開 settings.py,找到 ALLOWED_HOSTS,將其修改為:
ALLOWED_HOSTS = [‘127.0.0.1’, 'localhost ', ‘.zmrenwu.com’]
指定了 ALLOWED_HOSTS 的值后,django 將只允許通過(guò)指定的域名訪問(wèn)我們的應(yīng)用,比如這里只允許通過(guò) 127.0.0.1,localhost 以及 zmrenwu.com 和其任意子域名(域名前加一個(gè)點(diǎn)表示允許訪問(wèn)該域名下的子域名)訪問(wèn)(即 HTTP 報(bào)文頭部中 Host 的值必須是以上指定的域名,通常你在瀏覽器輸入域名訪問(wèn)網(wǎng)站時(shí),Host 的值就會(huì)被設(shè)置為網(wǎng)站的域名),這樣可以避免 HTTP Host 頭攻擊。
2)Django 項(xiàng)目中會(huì)有一些 CSS、JavaScript 等靜態(tài)文件,為了能夠方便地讓 Nginx 處理這些靜態(tài)文件的請(qǐng)求,我們把項(xiàng)目中的全部靜態(tài)文件收集到一個(gè)統(tǒng)一的目錄下,這個(gè)目錄通常位于 django 項(xiàng)目的根目錄,并且命名為 static。為了完成這些任務(wù),需要在項(xiàng)目的配置文件里做一些必要的配置:
文件位置:blogproject/settings.py
STATIC_ROOT 即指定靜態(tài)文件的收集路徑,這里指定為 BASE_DIR(項(xiàng)目根目錄,在 settings.py 文件起始處定義)下的 static 文件夾。
3)使用 git上傳代碼至服務(wù)器。首先安裝 git:
sudo yum install -y git
將代碼上傳到 GitHub 等代碼托管平臺(tái),這樣我們就可以方便地把代碼拉取到服務(wù)器了。如何將pycharm中的項(xiàng)目上傳至github上,請(qǐng)戳這里。
通常將應(yīng)用代碼放在 ~/apps/ 目錄下,先來(lái)設(shè)置一下服務(wù)器的文件結(jié)構(gòu),用于存放應(yīng)用代碼等相關(guān)文件:
#在用戶目錄下創(chuàng)建 apps 目錄并進(jìn)入
mkdir -p ~/apps
cd ~/apps
#拉取博客代碼
git clone https://github.com/fanxindong/HelloDjango-blog-tutorial-fxd.git
注意:上傳的項(xiàng)目代碼,需要將其中數(shù)據(jù)庫(kù)遷移時(shí)生成的代碼刪除,在服務(wù)器上重新遷移!
然后進(jìn)入到項(xiàng)目根目錄,安裝項(xiàng)目依賴:
cd ~/apps/HelloDjango-blog-tutorial
pipenv install --deploy --ignore-pipfile
然后創(chuàng)建一下數(shù)據(jù)庫(kù):
pipenv run python manage.py makemigrations
pipenv run python manage.py migrate
此時(shí)查看目錄發(fā)現(xiàn)已經(jīng)生成數(shù)據(jù)庫(kù)文件db.sqlite3
4)啟動(dòng)開發(fā)服務(wù)器:
pipenv run python manage.py runserver 0.0.0.0:8000
在瀏覽器中輸入服務(wù)器域名和端口號(hào),出現(xiàn)博客內(nèi)容!
5.使用 Gunicorn
首先進(jìn)入到項(xiàng)目根目錄,安裝 Gunicorn:
pipenv install gunicorn
由于我們?cè)诜?wù)端修改安裝了 gunicorn,代碼中 Pipfile 文件和 Pipfile.lock 文件會(huì)被更新,因此別忘了把改動(dòng)同步到本地,具體做法可以自行學(xué)習(xí),以下是一個(gè)參考:
#服務(wù)端提交代碼
git add Pipfile Pipfile.lock
若此時(shí)報(bào)錯(cuò),則按照要求輸出github的name和email
[root@instance-6lf3j8lp HelloDjango-blog-tutorial-fxd]# git config --global user.name “your-name”
[root@instance-6lf3j8lp HelloDjango-blog-tutorial-fxd]# git config --global user.email your-email
git commit -m “add gunicorn dependency”
git push
#本地電腦中拉取代碼
git pull
如此時(shí)出現(xiàn)錯(cuò)誤,請(qǐng)戳這里
然后回到線上服務(wù)器,在項(xiàng)目根目錄,執(zhí)行下面的命令啟動(dòng)服務(wù):
pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 0.0.0.0:8000
打開瀏覽器顯示如下:
各個(gè)參數(shù)的含義:
1)-w 2 表示啟動(dòng) 2 個(gè) worker 用于處理請(qǐng)求(一個(gè) worker 可以理解為一個(gè)進(jìn)程),通常將 worker 數(shù)目設(shè)置為 CPU 核心數(shù)的 2-4 倍。
2)-k gthread 指定每個(gè) worker 處理請(qǐng)求的方式,根據(jù)大家的實(shí)踐,指定為 gthread 的異步模式能獲取比較高的性能,因此我們采用這種模式。
3)-b 0.0.0.0:8000,將服務(wù)綁定到 8000 端口,運(yùn)行通過(guò)公網(wǎng) ip 和 8000 端口訪問(wèn)應(yīng)用。
4)訪問(wèn) ip:8000(ip 為你服務(wù)器的公網(wǎng) ip),應(yīng)用成功訪問(wèn)了,但是我們看到樣式完全亂了。別急,這不是 bug!此前我們使用 django 自帶的開發(fā)服務(wù)器,它會(huì)自動(dòng)幫我們處理靜態(tài)樣式文件,但是 Gunicorn 并不會(huì)幫我們這么做。因?yàn)樘幚盱o態(tài)文件并不是 Gunicorn 所擅長(zhǎng)的事,應(yīng)該將它交給更加專業(yè)的服務(wù)應(yīng)用來(lái)做,比如 Nginx。
6.啟動(dòng) Nginx 服務(wù)器
Nginx是一個(gè)高性能的 HTTP 和反向代理 web 服務(wù)器,它的功能非常多,這里我們主要用它來(lái)處理靜態(tài)文件以及將非靜態(tài)文件的請(qǐng)求反向代理給 Gunicorn。當(dāng)我們?cè)L問(wèn)一個(gè)博客文章詳情頁(yè)面時(shí),服務(wù)器會(huì)接收到下面兩種請(qǐng)求:
對(duì)于前一種請(qǐng)求,博客文章的數(shù)據(jù)需要借助 django 從數(shù)據(jù)庫(kù)中獲取,Nginx 處理不了,它就會(huì)把這個(gè)請(qǐng)求轉(zhuǎn)發(fā)給運(yùn)行在 Gunicorn 服務(wù)中的 django 應(yīng)用,讓 django 去處理。
用 django 去獲取靜態(tài)文件是很耗時(shí)的,但 Nginx 可以很高效地處理,因此對(duì)于后一種靜態(tài)文件的請(qǐng)求,只需要去這些靜態(tài)文件所在的文件夾獲取,Nginx 就會(huì)代為處理,不再麻煩 django。
首先安裝 Nginx:
sudo yum install epel-release -y
sudo yum install nginx -y
運(yùn)行下面的命令啟動(dòng) Nginx 服務(wù)
service nginx start
小貼士:
service nginx start(啟動(dòng))
service nginx stop(停止)
service nginx reload(重啟)
在瀏覽器輸入 ip(不輸入端口則默認(rèn)為 80 端口,Nginx 默認(rèn)在 80 端口監(jiān)聽請(qǐng)求),看到 Nginx 的歡迎界面說(shuō)明 Nginx 啟動(dòng)成功:
7.配置 Nginx
Nginx 的配置位于 /etc/nginx/nginx.conf 文件中,其內(nèi)容如下:
user nobody nobody; ... http {# Load modular configuration files from the /etc/nginx/conf.d directory.# See http://nginx.org/en/docs/ngx_core_module.html#include# for more information.include /etc/nginx/conf.d/*.conf;server {listen 80 default_server;listen [::]:80 default_server;server_name _;root /usr/share/nginx/html;# Load configuration files for the default server block.include /etc/nginx/default.d/*.conf;location / {}} }在 http 配置下有一個(gè) server 模塊,server 模塊用于配置一個(gè)虛擬服務(wù),使這個(gè)虛擬服務(wù)監(jiān)聽指定的端口和域名。你可以配置多個(gè) server,這樣就會(huì)啟動(dòng)多個(gè)虛擬服務(wù),用于監(jiān)聽不同端口,或者是同一個(gè)端口,但是不同的域名,這樣你就可以在同一服務(wù)器部署多個(gè) web 應(yīng)用了。
再來(lái)看看 server 下的 include,include 會(huì)將指定路徑中配置文件包含進(jìn)來(lái),這樣便于配置的模塊化管理,例如我們可以把不同 web 應(yīng)用的配置放到 /etc/nginx/conf.d/ 目錄下,這樣 nginx 會(huì)把這個(gè)目錄下所有以 .conf 結(jié)尾的文件內(nèi)容包含到 nginx.conf 的配置中來(lái),而無(wú)需把所有配置都堆到 nginx.conf 中,使得配置文件十分臃腫。
我們來(lái)配置博客應(yīng)用,為了模塊化管理,我們將配置寫到 /etc/nginx/conf.d/ 目錄下。先在服務(wù)器的 conf.d 目錄下新建一個(gè)配置文件,把它叫做 HelloDjango-blog-tutorial-fxd.conf。寫入下面的配置內(nèi)容:
文件位置:/etc/nginx/conf.d/HelloDjango-blog-tutorial-fxd.conf
首先我們配置了一個(gè)虛擬服務(wù),編碼方式為 utf-8,監(jiān)聽于 80 端口。
服務(wù)的域名為 www.fanxindong.com,所以來(lái)自這個(gè)域名的請(qǐng)求都會(huì)被這個(gè)服務(wù)所處理。
所有URL 匹配 /static 的請(qǐng)求均由 Nginx 處理,alias 指明了靜態(tài)文件的存放目錄,這樣 Nginx 就可以在這個(gè)目錄下找到請(qǐng)求的文件返回給客戶端。
其它請(qǐng)求轉(zhuǎn)發(fā)給運(yùn)行在本機(jī) 8000 端口的應(yīng)用程序處理,我們會(huì)在這個(gè)端口啟動(dòng) Gunicorn 用于處理 Nginx 轉(zhuǎn)發(fā)過(guò)來(lái)的請(qǐng)求。
重啟 nginx 使得配置生效:
service nginx reload
8.關(guān)閉 DEBUG 模式,收集靜態(tài)文件
開發(fā)環(huán)境下,django 為了調(diào)試方便,會(huì)將 settings.py 文件中的 DEBUG 選項(xiàng)配置為 True,這樣如果程序運(yùn)行出錯(cuò),調(diào)試信息將一覽無(wú)余,這在開發(fā)時(shí)很方便,但部署到線上就會(huì)帶來(lái)巨大安全隱患,所以我們把 DEBUG 選項(xiàng)設(shè)置為 False,關(guān)閉調(diào)試模式,在本地將 settings.py 中的 DEBUG 為:
DEBUG=False
線上服務(wù)器更新最新的代碼,然后運(yùn)行命令收集靜態(tài)文件到之前配置的 STATIC_ROOT 目錄下:
pipenv run python manage.py collectstatic
然后使用 Gunicorn 啟動(dòng)服務(wù)。
pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 0.0.0.0:8000
9.使用 Supervisor管理 Gunicorn 進(jìn)程
現(xiàn)在 Gunicorn 是我們手工啟動(dòng)的,一旦我們退出 shell,服務(wù)器就關(guān)閉了,博客無(wú)法訪問(wèn)。就算在后臺(tái)啟動(dòng) Gunicorn,萬(wàn)一哪天服務(wù)器崩潰重啟了又得重新登錄服務(wù)器去啟動(dòng),非常麻煩。為此使用 Supervisor 來(lái)管理 Gunicorn 進(jìn)程,這樣當(dāng)服務(wù)器重新啟動(dòng)或者 Gunicorn 進(jìn)程意外崩潰后,Supervisor 會(huì)幫我們自動(dòng)重啟 Gunicorn。
先按 Ctrl + C 停止剛才啟動(dòng)的 Gunicorn 服務(wù)進(jìn)程。
首先安裝 Supervisor。
sudo pip3 install supervisor
設(shè)置如下的目錄結(jié)構(gòu)(位于 ~/etc 目錄下)來(lái)管理 Supervisor 有關(guān)的文件:
~/etc
├── supervisor
│ ├── conf.d
│ └── var
│ ├── log
└── supervisord.conf
其中 supervisord.conf 是 Supervior 的配置文件,它會(huì)包含 conf.d 下的配置。var 目錄下用于存放一些經(jīng)常變動(dòng)的文件,例如 socket 文件,pid 文件,log 下則存放日志文件。
指令:
mkdir -p ~/etc/supervisor/conf.d
mkdir -p ~/etc/supervisor/var/log
然后進(jìn)入 ~/etc 目錄下生成 Supervisor 的配置文件:
cd ~/etc
echo_supervisord_conf > supervisord.conf
首先找到 [unix_http_server] 版塊,將 file 設(shè)置改為如下的值:
[unix_http_server]
file=/home/fxd/etc/supervisor/var/supervisor.sock
即讓 socket 文件生成在 ~/etc/supervisor/var/ 目錄下。注意 supervisor 不支持將 ~ 展開為用戶 home 目錄,所以要用絕對(duì)路徑指定
logfile=/home/fxd/etc/supervisor/var/log/supervisord.log
pidfile=/home/fxd/etc/supervisor/var/supervisord.pid
user=fxd
serverurl=unix:///home/fxd/etc/supervisor/var/supervisor.sock
files = /home/fxd/etc/supervisor/conf.d/*.ini
[program:hellodjango-blog-tutorial]
command=pipenv run gunicorn blogproject.wsgi -w 2 -k gthread -b 127.0.0.1:8000
directory=/home/fxd/apps/HelloDjango-blog-tutorial-fxd
autostart=true
autorestart=unexpected
user=fxd
stdout_logfile=/home/fxd/etc/supervisor/var/log/Hellodjango-blog-tutorial-fxd-stdout.log
stderr_logfile=/home/fxd/etc/supervisor/var/log/Hellodjango-blog-tutorial-fxd-stderr.log
各項(xiàng)配置的含義:
[program:hellodjango-blog-tutorial] 指明運(yùn)行應(yīng)用的進(jìn)程,名為 hellodjango-blog-tutorial。
command 為進(jìn)程啟動(dòng)時(shí)執(zhí)行的命令。
directory 指定執(zhí)行命令時(shí)所在的目錄。
autostart 隨 Supervisor 啟動(dòng)自動(dòng)啟動(dòng)進(jìn)程。
autorestart 進(jìn)程意外退出時(shí)重啟。
user 進(jìn)程運(yùn)行的用戶,防止權(quán)限問(wèn)題。
stdout_logfile,stderr_logfile 日志輸出文件。
supervisord -c ~/etc/supervisord.conf
-c 指定 Supervisr 啟動(dòng)時(shí)的配置文件。
進(jìn)入 supervisorctl 進(jìn)程管理控制臺(tái):
supervisorctl -c ~/etc/supervisord.conf
執(zhí)行 update 命令更新配置文件并啟動(dòng)應(yīng)用。
瀏覽器輸入域名,可以看到服務(wù)已經(jīng)正常啟動(dòng)了。
10.使用 CDN 加快 Bootstrap 和 jQuery 的加載速度
我們的項(xiàng)目使用了 Bootstrap 和 jQuery,這兩個(gè)文件我們是從本地加載的。如果服務(wù)器性能比較差的話,加載需要耗費(fèi)很長(zhǎng)的時(shí)間,網(wǎng)站打開的速度就變得無(wú)法忍受。我們使用 CDN 來(lái)加快加載速度。具體來(lái)說(shuō),替換 base.html 的幾個(gè)靜態(tài)文件的加載標(biāo)簽:
文件位置:base.html
- <link rel="stylesheet" href="{% static 'blog/css/bootstrap.min.css' %}"> - <script src="{% static 'blog/js/jquery-2.1.3.min.js' %}"></script> - <script src="{% static 'blog/js/bootstrap.min.js' %}"></script> + <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> + <script src="https://cdn.bootcss.com/jquery/2.1.3/jquery.min.js"></script> + <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>本地修改代碼后,將代碼同步到線上服務(wù)器,執(zhí)行下面的命令重啟 hellodjango-blog-tutorial 應(yīng)用進(jìn)程:
supervisorctl -c ~/etc/supervisord.conf restart hellodjango-blog-tutorial
這樣網(wǎng)站訪問(wèn)的速度將大大提升!
總結(jié)
以上是生活随笔為你收集整理的Diango博客--11.Nginx + Gunicorn + Supervisor 方式部署的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: spss 因子分析
- 下一篇: 计算机多系统启动光盘制作,U盘多系统启动