iT邦幫忙

2022 iThome 鐵人賽

DAY 28
1
Modern Web

Vue+Django+MongoDB+Nginx 全端開發系列 第 28

用 Nginx 部署 production back-end server

  • 分享至 

  • xImage
  •  

保護後端重要資訊

在 django 專案中我們會把設定都寫在 settings.py 內,包含了 SECRET_KEY 等機密資訊,通常專案都會做版本控制上 git,但把這些機密資訊也上 git 是很不好的一件事,畢竟 github 也是曾經被駭過的,所以最好是把這些不想讓別人知道的資訊寫在另外一個檔案內然後要用的時候再 import 進來,再來就是專案如果要部署在多台 server,每個 server 的設定都不一樣,所以我覺得每一台 server 要不一樣的設定檔不上 git 會比較好

env.json

我的做法是另外寫一個 env.json 去記錄,然後不要上 git,但是還是要告訴別人這個專案要寫一個 env.json,所以另外還會再寫一個示範檔案 env.json.default 告訴別人裡面該寫什麼,這個 env.json.default 就會上 git

內容如下

{
  "debug":false,
  "SECRET_KEY":"your_django_SECRET_KEY",
  "DB_HOST":"192.168.0.1:27017,192.168.0.2:27017,192.168.0.2:27017",
  "DB_ROOT_USER":"DB_ROOT_USER",
  "DB_ROOT_PASSWORD":"DB_ROOT_PASSWORD",
  "allow_host":["127.0.0.1",".localhost"]
}
  • debug: 在開發模式下,我們會設 debugtrue,在正式部署時要設定為 false,不然別人可以透過輸入 api 看到 debug 以及專案上的資訊
  • SECRET_KEY: 每一個 django 專案都會不一樣,以之前的例子來說,我們會用 SECRET_KEY 來產生專屬於這個專案的 token
  • DB_HOST: 我是會把資料庫的 host 也寫在這,萬一資料庫需要改 host,直接在這邊改就好了
  • DB_ROOT_USER: db 的 root user
  • DB_ROOT_PASSWORD: db root user 的密碼
  • allow_host: 允許後端架在哪些 host,強烈建議不要設定 allow_host 是 ["*",],很多教學為了方便起見都會教你這樣設定讓你架在哪都行,但這樣駭客對你發出請求,也是隨便從哪裡都可以。設定 allow_host 只包含你想架在哪個 ip 或 domain 就好,注意如果要設定允許架在哪個 domain,寫法要像 .back-end-domain,域名前面要在加個 .,這是 django 的寫法

settings.py

回到 settings.py,在最上面加入

import json
env = json.load(open('./back_end/env.json'))
DB_HOST = env['DB_HOST']
DB_ROOT_USER = env['DB_ROOT_USER']
DB_ROOT_PASSWORD = env['DB_ROOT_PASSWORD']

其他設定

SECRET_KEY = env['SECRET_KEY']
...
DEBUG = env['debug']
...
ALLOWED_HOSTS = env['allow_host']

之後在 views.py 內連接 db 會像這樣

from django.conf import settings
db_host = settings.DB_HOST
db_root_user = settings.DB_ROOT_USER
db_root_password = settings.DB_ROOT_PASSWORD
...
def func1(request):
    myclient = pymongo.MongoClient(
    'mongodb://'+db_root_user+':'+db_root_password+'@'+db_host+'+'/?authSource=admin')

WSGI

部署一個後端 service 和部署前端網站的方式不太一樣,前端架站很簡單,基本上就是架站工具 + web bundle 就結束了,如下圖

https://ithelp.ithome.com.tw/upload/images/20220927/20132990z7Zf1Tv5MX.png

而部署後端服務需要在架站工具和 application 之間建立一個 Web Server Gateway Interface (WSGI),如下圖

https://ithelp.ithome.com.tw/upload/images/20220927/20132990vrB99ePE7L.png

uWSGI

python 後端這邊最常用來實作 WSGI 應該就是 uWSGI,直接用 pip 安裝

pip install uwsgi

來創建一個 uWSGI 的設定檔,名稱叫什麼都可以,副檔名是 ini 就好,放在哪也都可以,我的話都是放在後端專案底下

[uwsgi]
socket = 127.0.0.1:8000
chdir = /path-to-your-backend-project
module = back_end.wsgi
home = /path-to-your-python-virtual-environment
  • socket: 你想把 WSGI 哪,把他架在 localhost 就好了,然後再串到 Nginx 對外,就可以讓外部使用後端了
  • chdir: 你的後端專案路徑
  • module: 在 django 專案根目錄下有一個 wsgi.py,這個就是來串 WSGI 的,架設你的專案叫 back_end,那就設定 module = back_end.wsgi
  • home: 你的 python 虛擬環境路徑

再來把 WSGI 跑起來

uwsgi --ini /path-to-yourfile.ini

ASGI

講完 WSGI ,我想講一下 ASGI,ASGI 全名是 Asynchronous Server Gateway Interface,可以想像是 WSGI 的升級版,WSGI 是比較舊的東西,並不支持一些新的網路協定和技術,所以為了支持新的網路技術,有了 ASGI 出現,但這我也還在研究中,不過 WSGI 在 web2.0 的使用中已經足夠好了,大部分的 python 後端也是用 WSGI,用到 ASGI 還是比較少的

virtual host

在串後端和 WSGI 前,想先介紹 virtual host 這個技術,我們在架網站的時候,都會架在 80 port 或是 443 port,也就是 http port 和 https port,可是一台 server 只有一個 80 或 443 port 啊,那我想部署多個專案再同台 server 的 80 或 443 port 怎麼辦呢?這個時候就要用到 virtual host 這個技術啦!

我們先在 nginx 目錄下新增 sites-availablesites-enabled 兩個資料夾,然後在 sites-available 新增一個文件,比方說你有個網站要架在 blog.mydomain.com,那就新增一個文件叫 blog.mydomain.com,裡面的內容就是這個網站的設定,所以我們會有很多個網站的設定寫在個別的文件,然後如果要使用這個網站,就做個連結放到 sites-enabled

再來要改 nginx.confhttp 部分的內容,原本裡面是長得像這樣

http {
    ...
    server {
        listen 80;
        server_name  your_domain_name;
        return 301 https://your_domain_name;
    }

    server{
        listen       443 ssl http2;
        server_name  your_domain_name;

        ssl_certificate      /etc/letsencrypt/live/your_domain_name/fullchain.pem;
        ssl_certificate_key  /etc/letsencrypt/live/your_domain_name/privkey.pem;

        location / {
            root   path_of_web_bundle;
            index  index.html index.htm;
        }
    }
    include servers/*;
}

現在改成這樣

http {
    ...
    
    include sites-enabled/*;
}

引入 sites-enabled 中所有的網站設定

部署正式的後端 server

好啦,WSGI 架起來後,在 sites-available 內新增一個後端網站的設定檔,內容如下

server{
    listen 80;
    server_name  back-end.mydomain.com;
    return 301 https://back-end.mydomain.com;
}

server{
    listen       443 ssl;
    server_name  back-end.mydomain.com;
    ssl_certificate /etc/letsencrypt/live/back-end.mydomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/back-end.mydomain.com/privkey.pem;
    
    location / {            
        include  uwsgi_params;
        uwsgi_pass  127.0.0.1:8000;      
    }
}

主要是 location / 裡面的設定有區別,我們需要 include uwsgi 的參數,這個東西 nginx 預設已經有幫你寫好了,不用改,再來就是 uwsgi_pass 要設定你剛剛把 uWSGI 架在哪裡,然後把這個設定做個連結到 sites-enabled 內,再 reload 一下 nginx 就大功告成囉!


上一篇
用 Nginx 部署前端網站
下一篇
讓網站更安全,不准直接連我的網站 IP
系列文
Vue+Django+MongoDB+Nginx 全端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言