部署方式
網路上部署教學非常多,但 95%都是教怎麼透過第三方部署平台例如 Heroku,Azure,GCP
…等,但我就是想架在自己架設的 Ubuntu 主機上阿!而關於各式部署方法及各自的優缺點我會再另外寫一篇文章,此篇就不多加贅述
使用的工具、系統
此篇教學主要是在 Ubuntu 實作,當然用 Windows 也可以,但建議若想更有效率的管理伺服器,Linux 是必備技能,功能跟穩定性都是直接把 Windows 壓在地板上磨擦.
本篇教學重點會著重於 Django,uWSGI,Nginx
,其餘提到的技術我會在專門另寫文章給大家參考
DNS 基礎知識
當使用者輸入 Domain Name 後,Web 必須要先去一台有 Domain Name 和 IP 對應資料的主機去查詢這台電腦的 IP,而這台被查詣的主機為 Domain Name Server,簡稱 DNS.
Ex:當你輸入www.shopee.com.tw
時,Web 就會將 www.shopee.com.tw
傳送最近的 DNS Server 去做辨識,若查詢有結果,則會傳回這台主機的 IP,進而跟它索取資料,若沒查到,就會發生 DNS NOT FOUND 的情形,而每個 Domain Name 對應要一組 IP,且 Domain Name 跟 IP 一樣不會重覆
一般架設網站時不管你是 Code from Scratch 還是用 Wordpress 等都需申請 DNS 指向你的 IP,畢竟大家也不可能去記 IP 位址來找網站吧,申請完後才辦法讓自己以外的人找到你自行定義的網域
購買網域
我購買網域的平台為 cloudflare,個人認為他的平台是我用過 UI 最人性化且支援暗黑模式的,未來有購買網域需求不妨去 Cloudflare 網域管理平台 看看
開始之前
連進 Server 第一件事不外乎就是先更新所有套件庫
1 | sudo apt-get update && sudo apt-get upgrade -y |
建立 Virtual Enviornment(虛擬環境)
不管是開發中小、大型專案,建立一個獨立的開發環境是個好習慣,能讓自己或開發團隊都比較好 Debug 且不會有一堆不需要的套件而造成需要去追源碼的情況發生
1 | sudo apt-get install python3-venv |
虛擬環境
建立完後檢查是否真的已在虛擬環境中,檢查目前 Python 是跑 global 還是 venv 裡的
建立 Django 專案
現在建立一個開發環境的前置作業相較以前簡單許多,不需要先架好 Server 就能直接開始寫 Code 了
1 | pip install django |
建立完後就先來python manange.py runserver
看是否有問題,預設為:8000 PORT,成功的話應看到以下畫面
測試網域是否運作正常
再來嘗試用你申請好的網域名稱去網頁試跑看看是否成功,若出現 DisallowedHost 錯誤代表你需要去你建立好的 Django 專案的settings.py的ALLOWED_HOSTS['']
新增你的網域名稱。
注意!!!如果你的網路環境或主機設定有防火牆或其他限制,可能會導致從遠端無法連接到你的主機,也就是說用 0.0.0.0:8000 去 runserver 反而會連不到。我的情況就是只有內部網路能存取
1 | #settings.py |
ALLOWED_HOSTS 預設為空白,意思就是除了 localhost 以外其他的外部 IP 都無法連上這個網站
測試 uWSGI 是否有作用
在還沒在 Nginx 設定 .conf 檔前,記得永遠都是去 0.0.0.0:8000 或是 (防火強有擋的話就主機內部IP)192.168.1.101 去看結果畫面,而不是申請好的 DNS 網址(Ex:py.butyshop.com),畢竟還沒去 /etc/nginx/sites-available 寫 .conf 檔, uWSGI 也不知道要導到哪裡去。
uWSGI 可想成是 Django 跟 Server 的中繼站,它是 Python 程式及如 Django,Flask 等和 Web 服務之間的一種接口,可以處理大量的並發請求,支持多種協議和輸入輸出格式,包括 HTTP、FastCGI、SCGI、WebSocket、UDP、TCP 等。
1 | sudo apt-get install python3.10-dev |
最終目標就是要將 client 端的 requests 傳送給 Nginx 並傳遞給暫存 socket 後,socket 會再拿給 uWSGI 處理最後才終於傳到 Django。
編寫測試 uWSGI
建立一個 test.py 測試一下 uWSGI 的功能
1 | # test.py |
寫好後去終端機下 uWSGI 指令,這步是為了測試 uWSGI 是否有成功與 Django 取得聯繫
1 | uwsgi --http :8000 --wsgi-file test.py |
此時你去yourdomain:8000
看到 “Hello World!”,代表 uWSGI 成功將請求傳遞給 Python。接下來就可以使用以下命令類似地使用 uWSGI 服務 Django 項目。此時再去yourdomain:8000
應能看到 Django 預設畫面。
1 | uwsgi --http :8000 --module <FolderName>.wsgi # Django專案底下的 wsgi.py |
如果這一步畫面顯示了Internal Server Error
,不妨看一下虛擬環境 venv 有沒有啟動。
Nginx Server 設定
最後終於來到 Server 端的部分,不多說廢話,直接開始
1 | sudo apt-get install nginx |
此時你在去http://yourdomain
查看應能看到 Nginx 下載成功的 “Welcome to nginx!”頁面
Nginx .conf 檔案設定
此時去主機的/etc/nginx/sites-available
建立 nginxConfig.conf
,yourdomain
= 申請好的 DNS 網址名稱
1 | # the upstream component nginx needs to connect to |
uwsgi_params
這個檔案是在專案目錄底下而不是 nginx 目錄底下,我的話就是在/home/httpd/django_project_name
這建立 uwsgi_params。
- 用於定義轉發到 uWSGI 服務器的 HTTP 請求參數。
- 此文件列出了所有必要參數,以便 Nginx 可以通過正確的方式將請求傳遞給 uWSGI。
- 例如:QUERY_STRING 定義了 HTTP 請求中的查詢字符串。uWSGI 需要這些變量來識別請求的內容,並正確地將其轉發到相應的應用程序。
1 | # /home/xxxxx/<project_name>/uwsgi_params |
建立軟連結
告訴 Nginx 我這個網址要啟用了,一般可以把所有網站寫到include
檔內就不必每次都得寫這行
1 | sudo ln -s /etc/nginx/sites-available/yourdomains.conf /etc/nginx/sites-enabled/ |
讓 Nginx 知道 static_files 的位置
我自己會習慣將靜態檔案位置設定加在最下方
1 | import os |
最後執行這行,這步驟是要告訴 Django 將我們的靜態檔案js,css,img
…等等全部打包進我們指定的目錄底下
1 | python manage.py collectstatic |
重啟 Nginx Server
1 | sudo -s nginx reload |
若成功應該就會在http://yourdomain/media/test.png
看到你放進指定的目錄的圖片了
使 Nginx, uWSGI, Django 成功串接
讓 uWSGI 生成 socket 來達到雙向溝通的目的,chmod666
是為了要讓 socket 有權限寫入檔案
1 | uwsgi --socket yourdomains.sock --module yourdomains.wsgi --chmod-socket=666 |
--socket microdomains.sock
: 指定 uWSGI 與應用程序之間通訊的 socket 名稱,這裡命名為 “yourdomains.sock”。--module microdomains.wsgi
: 指定要運行的 Python 模塊,這裡為 "microdomains.wsgi ",這個模塊中包含了應用程序的主要邏輯。--chmod-socket=666
: 設置 socket 文件的權限,這裡設置為 666=所有用戶都可以對其進行讀寫(rw)。
撰寫 uWSGI.ini (正式用)
在正式發佈階段時 uWSGI 夾帶的參數指令會變得較繁雜,因此直接寫一個.ini
檔就可省得每次都得打一長串
1 | [uwsgi] |
之後在執行 uwsgi 指令只需簡潔的一行即可
1 | uwsgi --ini yourdomains_uwsgi.ini |
成功畫面
最後在去你自己的網址 http://yourdomain.com
就能看到 Django 初始頁面了!此時把此網址貼給你的朋友,他也能看到屬於你自己的網站了。
Emperor mode
何謂emperor mode
?一般會在大型專案開發時遇到,在這種模式下,uWSGI 啟動一個特殊的 master 進程,稱為"emperor",該進程可以監控一個或多個虛擬主機或應用程序的進程。
這些虛擬主機或應用程序可以是不同的 Python 應用程序,也可以是不同的框架或應用程序。有興趣了解他的功能可以直接去看官方 docs
1 | # 去 venv 目錄下新增 vassals 資料夾 |
更改 uwsgi.ini 的 uwsgi-emperor.log 位置
由於原本我的 uwsgi-emperor.log 的位置是跟其他專案一起放在/home/httpd/
之下,我覺得有點亂,因此我就想將換到/home/httpd/venv/vassals/
底下。
1 | # 編輯 uwsgi.ini |
改完路徑後還沒完,此時直接用 emperor mode 執行 uwsgi 會出現permission denined
的問題,代表他沒有權限可以編輯uwsgi-emperor.log
檔案。
1 | # 原本的權限狀態 |
這樣做的目的是為了確保 uwsgi 服務可以以 www-data 用戶和組的身份運行,這樣 uwsgi 就可以擁有對/home/httpd/venv/vassals/
目錄和其子目錄的讀取、寫入和執行權限。此時再執行uwsgi --emperor /home/httpd/venv/vassals/ --uid www-data --gid www-data
應就能看到預設畫面了。
開機自動執行程式碼
將執行程式寫入 rc.local 檔讓他開機自動背景執行
1 | sudo vim /etc/rc.local |
SSL 憑證
2022 年了,網路安全性已普及,因此只要能到的網站幾乎都是https://
,若網站沒有 SSL 憑證就不會有https://
,SEO 會大幅降低,也會被大多數瀏覽器封鎖,在.conf
裡面的那兩行 SSL_certificate 是申請 SSL 憑證的證明,關於 SSL 可以參考我的另外一篇文章 Hexo 部署至 Nginx 設置 CI/CD 流程,此篇就不再多加贅述。
用 letsencrypt 加上 SSL 憑證後,nginx 底下的 .conf 檔案就會自動將 80 PORT 轉 443。listen 443 ssl;
會自動出現
完成
感謝大家的閱讀,若有問題歡迎留言。
若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~
留言版