本文主要介紹如何在Linux平台上部署Django相關項目,關於Django項目的部署在互聯網論壇上有很多的資料,筆者在查閱眾多資料並經過實踐后發現結果並不如意(或多或少總是遇到一些問題,往往與資料的預期不相符)。在瀏覽了許多資料后筆者整理得出了部署Django項目的一般性方法,部署的方法有很多種,在此筆者選擇了較為常用的基於uwsgi和Nginx的部署方案。
一、前提准備
部署前主要是需要做一些與服務器相關的准備工作,本次教程的服務器采用了阿里雲的 CentOS 7.3 64位,當然作為資料學習大家也可使用Linux虛擬機進行部署。另外,為了方便的Linux的使用和部署操作,在此推薦大家安裝XSHELL(https://www.netsarang.com/en/xshell/)和XFTP(https://www.netsarang.com/en/xftp/),XSHELL主要是用於連接服務器並進行終端操作,而XFTP則可用來進行服務器與開發主機的文件傳輸(比如windows和linux間的傳輸)。


在此還需要注意的是,如果大家和我一樣使用阿里雲服務器,那么在部署前還需要留意一下設置相應的網絡安全組,這個安全組主要是用於設置外網對服務器端口的訪問權限,由於阿里雲服務器中有的端口默認未開啟被訪問,所以為了能夠讓外網訪問到部署的項目(比如Django網站),那么就需要開啟相應的端口(比如80端口)。安全組設置可在阿里雲控制台(https://ecs.console.aliyun.com/)的服務器實例中查看到,如下左邊功能欄的【本實例安全組】,點擊進入后可在安全組列表中查看到相關規則設置,點擊【配置規則】后便可進行端口訪問權限的設置(比如下圖中新設置的80和8000端口)。



二、部署所需要安裝軟件的清單
本篇采用uwsgi和nginx的部署方案,因此在Linux環境下我們需要預先安裝好以下軟件,不過在此只做簡單的描述,讀者們有一個概念性的印象便可(如果想要深入理解可自行學習相關資料),各個軟件具體的安裝方法和使用操作將在后文一一講述。
- Python:因Lunix系統默認安裝了python2版本,但由於現在的Django項目主流是采用python3開發,因此我們還需要在服務器中安裝好python3的版本,並配置相關的環境變量以便在終端的直接使用。對於Linux下python3環境的安裝與搭建這一部分,限於篇幅,在此不進行闡述,各位讀者可以到互聯網上查詢相關的資料。
- uwsgi:uwsgi是一個基於python的應用服務器,它可充當網絡請求中文件的傳輸,也可以用於啟動Django項目。在我們的Django項目部署中,一般讓其充當非靜態文件的資源訪問中間服務器,外網可以借助於它來訪問Django項目的非靜態文件資源。當然,uwsgi也可以傳輸靜態資源,但在這一點上其性能並不高。
- nginx:nginx是一個高性能的HTTP和反向代理web服務器,它主要負責轉發外網的端口訪問請求,比如它可轉發80端口至uwsgi進程以訪問相關網站,而二者之間的聯系可通過socket進行關聯。另外由於nginx轉發性能之高,也可以用來做相關服務器,在Django項目中如果說uwsgi充當非靜態資源的中間服務器,那么nginx充當的角色便是靜態資源的中間服務器,它可以通過轉發特定的靜態http 請求來讓外網訪問到Django的靜態文件資源。
- supervisor:supervisor是一個進程管理工具,可通過fork/exec的方式將這些被管理的進程當作supervisor的子進程來啟動,並且當監聽的子進程異常中斷時,它還可以捕獲到相關信息並進行異常處理(比如重新啟動子進程)。在Django項目中,由於uwsgi命令行啟動Django項目是依賴於uwsgi進程的,當進程結束后Django項目也隨之結束,因此部署時我們可以把“啟動Django項目”的進程(比如uwsgi進程)作為supervisor的一個子進程,並開啟supervisor服務,以便在終端斷開后對部署進行監聽與管理。在supervisor中,包括supervisord和supervisorctl兩部分,前者為核心功能模塊,充當命令行命令功能,而后者則是一個控制台(類似於mysql控制台),亦可對進程進行管理。
總的來說,以上幾個模塊在Django項目中的關系可表述為下圖:

以上為部署項目最基本的軟件需求,具體的軟件環境還需要結合實際情況進行配置(比如一些項目可能需要mysql、memcache和redis等環境,那么還需要進行相關環境的搭建)
三、正式部署
本次部署工作分為兩個環節——開發主機和服務器主機,開發主機主要負責項目的開發與調試,確保項目質檢合格后方可在服務器主機中進行部署與運維操作。
(一)開發主機
在此以全新的Django 3.0項目為例進行闡述,並預先創建好了一個測試用的testapp,其主要是用於展示一個測試網站首頁,整體項目架構如下圖所示:
1. 測試Django項目
開啟DEBUG,在終端輸入如下命令開啟項目,並在瀏覽器訪問127.0.0.1:8000,觀察項目是否正常運行
$ python manage.py runserver 0.0.0.0:8000
2. 打包項目環境依賴
關閉DEBUG(注意部署在服務器上的需要將DEBUG設置為False,否則在后面的uwsgi和nginx環節會出錯),並在settings,py中設置ALLOWED_HOSTS和STATIC_ROOT兩個常量
- ALLOWED_HOSTS:用於設置可訪問的域名地址,即待部署服務器的域名或公網IP。
- STATIC_ROOT:用於設置靜態資源的收集目錄,在服務器項目中通過運行命令可將項目所有的靜態資源收集起來以方便后續Nginx的轉發訪問。
在此,筆者為方便DEBUG的切換,將兩種模式下的設置進行了如下整合:
# SECURITY WARNING: don't run with debug turned on in production! DEBUG = True if DEBUG == True: # 開發模式下允許所有域名訪問 ALLOWED_HOSTS = ['*'] else: # 發行模式下允許訪問的域名地址 ALLOWED_HOSTS = ['XXX.XXX.XXX.XXX'] # …… # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static'), ) if DEBUG == False: # 發行模式下設置靜態文件收集目錄,收集靜態文件以便后續 Nginx 的配置 STATIC_ROOT = os.path.join(BASE_DIR, 'static_dist')
之后運行命令打包項目的虛擬環境依賴,命令完成后在項目根目錄下可見到新生成的requirements.txt文件,這里面記錄着本項目所依賴的pip包,以便后續在服務器中的安裝。
$ pip freeze > requirements.txt
# requirements.txt
asgiref==3.2.3
Django==3.0.3
pytz==2019.3
sqlparse==0.3.0
3. 項目源文件遷移
將項目源文件(不含venv虛擬環境文件夾)通過XFTP傳輸到服務器中(比如本教程將其遷移至服務器下的’/srv/Django_projects/DjangoDistTest/’目錄下)

至此,開發主機的工作已全部完成.
(二)服務器主機(注:該教程中所有Linux命令均在root權限下操作)
1. 安裝python3環境和virtualenv虛擬環境管理工具
Linux下Python3環境的安裝在此不進行闡述,這里主要講解virtualenv的安裝與使用,同時為方便后文的講述,假設我們的python3安裝目錄為‘/usr/local/python3’。
virtualenv是python的一個虛擬環境管理工具,通過它可以很方便地創建一個python虛擬環境(這里稍微補充一下,虛擬環境是指拷貝式地創建一個與系統python版本一模一樣的python運行環境,但這個環境不包含任何多余的依賴包,我們可以在這個虛擬環境中根據項目針對性地安裝一些依賴包,從而方便python項目的管理並減少包的冗余)。
安裝命令
$ pip3 install virtualenv
設置軟鏈接
上文已經說明,軟鏈接是為了將一程序配置為命令以方便Linux直接在終端通過命令行進行操作
$ ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv
使用方法
直接在我們的項目目錄下執行相關命令,其中參數’python’指向所拷貝的源python程序
$ cd /srv/django_projects/DjangoDistTest
$ virtualenv --python=/usr/local/python3/bin/python3 venv
2. 安裝項目環境依賴並驗證
開啟虛擬環境,同時檢查所安裝的包
$ source ./venv/bin/activate
$ (venv) pip list

安裝項目依賴包,之后再次查看包若發現已裝上全部依賴則表示虛擬環境已搭建好
$ pip3 install -r requirements.txt

執行’python manage.py makemigrations’和’python manage.py migrate’進行數據庫遷移(如果之前將.sqlite3文件拷貝過來了,那么遷移時可能會不同,刪除.sqlite3文件即可;另外,對於不同版本的Linux,這一步可能會出現sqlite3文件錯誤,原因是系統未安裝sqlite3,因此查閱相關資料安裝sqlite3即可)
$ (venv) python manage.py makemigrations
$ (venv) python manage.py migrate

由於我們項目現在的DEBUG為關閉狀態,考慮到上文中的STATIC_ROOT設置,所以需要收集靜態文件資源(關於靜態資源路由的設置請參看文末附錄)
$ (venv) python manage.py collectstatic
![]()
之后運再次運行項目,在瀏覽器中訪問網址即可(服務器公網IP:8000或域名:8000)。另外,這里還需要留意一下阿里雲安全組是否已經設置好。

3. 安裝uwsgi
安裝命令
由於uwsgi是基於python編寫的,因此我們可以直接通過pip進行安裝(筆者之前在查閱資料時發現有的博主是通過CentOS 的yum進行安裝的,不過經實踐后操作效果不是那么好,因此還是推薦使用pip進行安裝)。這里需要注意的是,uwsgi由於是通過系統進程來調用,所以要在系統級別中安裝,因此我們需要預先退出虛擬環境再進行安裝。
$ (venv) deactivate
$ pip3 install uwsgi

建立軟鏈接
$ ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi
驗證安裝
直接使用uwsgi命令行形式開啟項目,參數http表示端口號,module表示項目的wsgi文件,home表示所使用的虛擬環境目錄
$ uwsgi --http :8000 --module DjangoDistTest.wsgi --home=/srv/django_projects/DjangoDistTest/venv/

之后使用瀏覽器進行訪問即可

上面這種通過命令行的方法已經可以啟動項目,但如果每次啟動項目都輸入一長串命令的話會比較費力,因此下面介紹通過ini文件配置的方式啟動項目
uwsgi.ini文件配置
在項目根目錄下新建ini文件(比如本例中的DjangoDistTest_uwsgi.ini),並輸入以下配置信息,之后便可通過運行命令’uwsgi –ini DjangoDistTest_uwsgi.ini’來啟動該項目了
# DjangoDistTest_uwsgi.ini
[uwsgi] # Django相關的設置 # 項目根目錄 chdir = /srv/django_projects/DjangoDistTest # Django的wsgi文件 module = DjangoDistTest.wsgi # 虛擬環境路徑 home = /srv/django_projects/DjangoDistTest/venv/ # 指定端口 http = :8000 # Django 和 uwsgi的相關日志記錄位置,注意要預先在項目中新建log文件夾 daemonize = /srv/django_projects/DjangoDistTest/log/uwsgi.log # 進程相關的設置 # 主進程 master = true # 最大數量的工作進程 processes = 10 # socket文件路徑,用於與 Nginx 進行通信 socket = /srv/django_projects/DjangoDistTest/DjangoDistTest.sock # 設置socket文件的權限 chmod-socket = 666 # 退出時是否清理環境 vacuum = true
$ uwsgi --ini DjangoDistTest_uwsgi.ini
![]()
4. 安裝Nginx
安裝命令
Nginx服務可以直接通過yum命令進行安裝
$ yum install nginx
驗證安裝
安裝完成以后,使用命令’systemctl start nginx’即可開啟nginx服務,之后使用瀏覽器訪問服務器公網ip(即http 80端口),若出現如下界面則表示nginx已成功啟動(有的系統可能會出現”Welcome to NGINX!”的歡迎界面,這兩種都是可以的,主要與系統版本和配置有關)
$ systemctl start nginx

當然,也可以通過命令’systemctl status nginx’查看nginx服務的狀態
$ systemctl status nginx

此外,還有相對應的restart和stop命令控制重啟和停止,后續感興趣的同學也可以把Nginx服務設置成開機自動啟動。(這里再補充一下下,對於以前版本的CentOS,需要將命令改寫成對應的”service nginx XXX”格式)
關聯uwsgi和Nginx
在完成好uwsgi和Nginx的安裝后,我們便可通過Nginx配置將二者進行關聯,即當外網訪問某一端口(比如80端口)時Nginx會自動轉發至相應的uwsgi服務器進行處理。這一關聯的映射文件存放在’/etc/nginx/conf.d’目錄下(新安裝的Nginx可能沒有該文件夾,需要自己手動創建一下),因此,我們在該目錄下新建相關映射文件DjangoDistTest.conf。(注意下面的server_name填上公網ip或域名)
# DjangoDistTest.conf
upstream DjangoDistTest { # 設置 socket 通信文件位置 server unix:///srv/django_projects/DjangoDistTest/DjangoDistTest.sock; } server { # 監聽的端口號 listen 80; # 域名 server_name XXX.XXX.XXX.XXX; #如果有域名的話,就寫上域名,比如"unikfox.cn wwwunikfox.cn XXX.XXX.XXX.XXX" charset utf-8; # 最大的文件上傳尺寸 client_max_body_size 75M; # 轉發非靜態文件請求到Django服務器 location / { uwsgi_pass DjangoDistTest; # uwsgi_params文件地址 include /etc/nginx/uwsgi_params; } # 轉發靜態文件 http 請求 location /static { alias /srv/django_projects/DjangoDistTest/static_dist; } }
之后重新啟動uwsgi和Nginx服務即可,由於上述配置中監聽了80端口,因此現在我們只需要通過在瀏覽器訪問服務器公網ip或域名即可訪問Django項目了(而不需要再填寫8000端口)

5. 使用supervisor管理進程
上文已經提到,uwsgi是一個進程,它有可能因為某些神秘力量而被迫終止,一旦uwsgi進程退出了那么它所對應的Django項目也就停止了,因此為了避免uwsgi的結束風險,我們可以使用supervisor工具進行進程管理,以使當uwsgi異常退出時能自行恢復。
安裝方法
使用pip3在系統級中進行安裝
$ pip3 install supervisor
建立軟鏈接(包括supervisord和supervisorctl兩部分)
$ ln -s /usr/local/python3/bin/supervisord /usr/bin/supervisord
$ ln -s /usr/local/python3/bin/supervisorctl /usr/bin/supervisorctl

配置文件
接下來,在項目根目錄下進行相關的文件配置即可(如本例中的”DjangoDistTest_supervisor.conf”)
# DjangoDistTest_supervisor.conf # supervisor程序名字 [program:DjangoDistTest] # supervisor執行命令 command = uwsgi --ini DjangoDistTest_uwsgi.ini # 項目的目錄 directory = /srv/django_projects/DjangoDistTest # 開始的時候等待多少秒 startsecs = 0 # 停止的時候等待多時秒 stopwaitsecs = 0 # 自動開始 autostart = true # 程序掛了后自動重啟 autorestart = true # 輸出的log文件 stdout_logfile = /srv/django_projects/DjangoDistTest/log/supervisord.log # 輸出的錯誤文件 stderr_logfile = /srv/django_projects/DjangoDistTest/log/supervisord.err [supervisord] # log的級別 loglevel = info # 設置supervisorctl管理員配置 [supervisorctl] # supervisorctl登錄的的地址和端口號,端口號可自定義 serverurl = http://127.0.0.1:XXXX # supervisorctl的用戶名和密碼 username = unikfox password = 123456 [inet_http_server] # supervisor的服務器,與上面serverurl的端口號一致 port = :XXXX # 用戶名和密碼 username = unikfox password = 123456 [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
啟動命令
之后便可在項目根目錄下使用命令啟動supervisor進程
$ supervisord -c DjangoDistTest_supervisor.conf
對於進入管理控制台,可使用如下的命令
$ supervisorctl -c DjangoDistTest_supervisor.conf
常用的管理命令:
- status # 查看狀態啊
- start program_name # 啟動程序
- restart program_name # 重新啟動程序
- stop program_name # 關閉程序
- reload # 重新加載DjangoTest_supervisor配置文件
- quit #推出控制台
使用'help'可查看supervisorctl所支持的所有命令
當然,除此以外,也還可以通過瀏覽器訪問配置文件中serverurl的方式管理進程

如此一來,Django項目的部署便大功告成啦~完結撒花"o((>ω< ))o"
這里還需要注意一點的是,重啟centOS后如需部署則需手動開啟以下兩個服務:
- 開啟nginx服務:'systemctl start nginx'
- 開啟相關項目的supervisor:'supervisord -c DjangoDistTest_supervisor.conf'
當然,大家也可以嘗試把這兩個設置成開機自動啟動,這樣就再也不用每次開機都手動輸入命令啦。
附錄——Django項目中urls.py下靜態文件和圖標的路由設置
# DjangoDistTest/urls.py
from django.contrib import admin from django.urls import path,include # 處理網站圖標 from django.views.generic.base import RedirectView # 處理靜態文件的訪問 from django.views import static from django.conf import settings from django.conf.urls import url urlpatterns = [ path('admin/', admin.site.urls), path('', include('testapp.urls')), url(r'^favicon.ico$', RedirectView.as_view(url=r'static/images/icon.ico')), #網站圖標 ] + [ url(r'^static/(?P<path>.*)$', static.serve, {'document_root': settings.STATIC_ROOT}, name='static') #靜態資源,只適用於DEBUG為False的情況 ]
以上便是本次的《CentOS 7 下Django項目部署(基於uwsgi和Nginx)》,Django項目的部署方式不止本案例一種,有關更多的部署方式大家可以查閱相關網絡資料,重要的是,只要適合自己的方式那它就是好的方式。
關於本教程,如各位讀者有一些疑問、想法或是更好的見解,歡迎留言交流與分享。


