服務器部署 Vue 和 Django 項目的全記錄

本篇記錄我在一個全新服務器上部署 Vue 和 Django 前後端項目的全過程,內容包括服務器初始配置、安裝 Django 虛擬環境、python web 服務器 uWSGI 和反向代理 Nginx 的使用,以及報錯的糾正等。

若前後端採用的技術棧和我相同,可基本按照本文進行操作;否則可能需要理解所涉及步驟的意義和使用,再結合自己的技術棧進行調整。

服務器預設

租服務器

各大雲平台,如騰訊雲、阿里雲、華為雲等,都有學生優惠。我選擇的是騰訊雲,原因:UI好看。

我所租借服務器的配置如下,僅供參考:

服務器配置

  • 鏡像信息:CentOS 7.6 64bit
  • 實例規格:CPU 1核,內存 2GB
  • 磁盤:系統盤 40GB
  • 流量包套餐:帶寬 5Mbps,流量包 1000GB/月(免費)

我使用的是 CentOS,關於 CentOS 和 Ubuntu 鏡像的選擇,可以參考 CentOS、Ubuntu、Debian三個linux比較異同 – 知乎

很多企業部署在生產環境的服務器使用的是 CentOS,但對於個人網站或者課內學習之用,我認為可能 Ubuntu 會方便一些也容易上手一些,從實操來看,很多 Ubuntu 能直接 apt 下載的東西,CentOS 要繞不少彎。

如果你選擇的是 Ubuntu,這篇文章也是能給你部署帶來幫助的,因為步驟大同小異

SSH 遠程連接

配置 SSH 遠程連接,方便本地操作服務器,而無需每次都登錄雲平台。

在控制台中點擊登錄,進入服務器終端。第一步需要初始化超級用戶 root 的密碼,進入 superuser 權限。

sudo passwd       # 初始化密碼
su                # 切換到root超級用戶

修改配置文件,允許密碼或密鑰遠程連接。

vim /etc/ssh/sshd_config      # 編輯ssh設置文件

在打開的文件中,修改:

RSAAuthentication yes                       # 開啟rsa驗證,需要添加
PubkeyAuthentication yes                    # 開啟公鑰登錄,一般被注釋掉了,去掉前面的#就好
AuthorizedKeysFile .ssh/authorized_keys     # 公鑰保存位置,原來就有
PasswordAuthentication yes                  # 開啟使用密碼登錄

保存退出,重啟 SSH 服務。

service sshd restart        # 重啟ssh服務

設置完畢後,即可在本地 powershell 或 git bash 連接服務器。

ssh root@<IP address>       # IP address 為你服務器的公網IP地址

另外,VScode 的 Remote – SSH 遠程連接插件真香。

添加用戶

所有命令都在 root 用戶下執行,這樣是不明智的,所以實現遠程連接後,我們在本地終端連接服務器,使用以下命令添加一個新用戶:

adduser <username>

為其指定密碼:

passwd <username>

如果服務器是本人的,還可以為創建的用戶添加 sudo 權限:

vim /etc/sudoers

將 root 所在行複製後改為用戶的 username,保存後該用戶則擁有 sudo 權限;另外設置需要密碼才能使用 sudo 權限,則設置後面字段為 ALL,不需要密碼則為 NOPASSWD:ALL。修改後大致為:

root      ALL=(ALL)       NOPASSWD:ALL
hadoop    ALL=(ALL:ALL)   ALL

配置公鑰

配置公鑰後,本地連接服務器,無需每次都輸入密碼。

首先,生成本地電腦的公鑰。

ssh-keygen -t rsa           # 打開cmd或powershell輸入

默認回車即可,成功後在 C:\Users\用戶名\.ssh 文件夾下會生成 id_rsaid_rsa.pub,後者就是本地用戶的密鑰。打開該文件,複製內容。然後使用 ssh 命令登錄遠程服務器,在用戶根目錄下(~/)創建 .ssh 文件夾並進入,再創建 authorized_keys 文件,將密鑰粘貼進去,之後重啟 ssh 服務。

service sshd restart        # 重啟ssh

更新系統軟件包

服務器的預配置都比較古老,依次輸入以下命令升級軟件包或依賴。

yum update -y                               # 更新系統軟件包
yum -y groupinstall "Development tools"     # 安裝軟件管理包
yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel psmisc libffi-devel epel-release     # 安裝可能使用的依賴

配置 Django

本步驟中,我在服務器上搭建 Django 環境,採用的是 virtualenv 虛擬環境管理器。當然我現在重新配置的話,可能不再會採用該方式了,我更推薦安裝 Anaconda 或者 Miniconda(服務器比較小型可選擇後者),通過 Conda 來管理 Python 環境會方便一些。

TODO: 也許我什麼時候會想寫篇博客簡單介紹一下 Conda

安裝 python3.8.4

CentOS 拿到手,發現不自帶高版本 Python 時,我是很懵的,這也是我推薦入門者用 Ubuntu 的原因之一。推薦歸推薦,當初我還是乖乖地給自己安了個 Python 3.8。

在執行以下操作前,請先輸入 python -V 查看一下本地 Python 版本,如果是 3.x 這一步就不需要做了。

cd /usr/local                   # 我一般喜歡把文件下載到該目錄下
wget //www.python.org/ftp/python/3.8.4/Python-3.8.4.tgz
tar -zxvf Python-3.8.4.tgz      # 解壓python包

進入 Python 包路徑,並編譯安裝到指定路徑 /usr/local/python3

cd Python-3.8.4
./configure --prefix=/usr/local/python3
make && make install

安裝成功後,建立軟鏈接,添加環境變量。因為服務器系統自帶有 python、python2、python3,因此我命名為 python3.8,避免衝突。但我的服務器只有 pip3 沒有 pip,所以我將 pip3.8 的軟連接命名為 pip。

ln -s /usr/local/python3/bin/python3.8 /usr/bin/python3.8
ln -s /usr/local/python3/bin/pip3.8 /usr/bin/pip

檢測是否安裝成功。

python3.8 -V
pip -V

安裝虛擬環境

建議安裝虛擬環境 virtualenv,當不同項目要求的 python 版本不同時,不會產生衝突。

pip install virtualenv
pip install virtualenvwrapper       # 管理虛擬環境

下載成功後,創建存儲虛擬環境的目錄。

mkdir ~/.virtualenvs                # 我一般存放在 /root/.virtualenvs,可自行修改

查找 virtualenvwrapper.sh 文件位置,添加環境。

find / -name virtualenvwrapper.sh

編輯 .bash_profile 文件,在末尾添加這兩句,其中 source 後的路徑為前面查到的路徑。

export WORKON_HOME=$HOME/.virtualenvs
source  /usr/local/python3/bin/virtualenvwrapper.sh

保存修改後,更新配置信息。

source ~/.bash_profile 

如果保存時報錯,在 /etc/profile 中加入下面內容,再 source

export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3.8
export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/python3/bin/virtualenv

創建虛擬環境

通過 -p 指定使用的Python版本,創建成功後自動進入該虛擬環境。

mkvirtualenv -p python3.8 django        # django為虛擬環境名稱

如果你希望將當前虛擬環境安裝的所有插件配置到新虛擬環境中,可以執行:

pip freeze > requirements.txt           # 導出依賴
pip install -r requirements.txt         # 進入新虛擬環境後再執行

虛擬環境的其它常用命令

  • 查看創建的全部虛擬環境:workon
  • 使用某一虛擬環境:workon 虛擬環境名稱
  • 退出當前虛擬環境:deactivate
  • 刪除虛擬環境:rmvirtualenv 虛擬環境名稱 記得退出再刪除

虛擬環境中安裝 Django 和 uWSGI

uWSGI 可以理解為服務器上持續運行 Django 的代理服務器,用於與 Django 後端進行數據傳輸等,後續配置需要使用。

進入前面創建的虛擬環境,安裝。

pip install django==3.2         # 可指定版本
pip install uwsgi

uWSGI 要安裝兩次,一次在虛擬環境中,另一次退出虛擬環境進行安裝

創建 uWSGI 的軟鏈接。

ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi

安裝 Nginx

Nginx 是 Http 反向代理 web 服務器,同時也提供 IMAP/POP3/SMTP 服務,佔用內存少,並發能力強。在這裡我們只需要了解,Nginx 能幫我們在指定端口跑我們的項目就好了。

yum install nginx

安裝成功後,相關的文件存儲路徑為

  • 安裝成功後,默認的網站目錄為 /usr/share/nginx/html
  • 默認的配置文件為 /etc/nginx/nginx.conf
  • 自定義配置文件目錄為 /etc/nginx/conf.d/

在啟動之前,還需確保服務器的相關端口已打開。http 對應 80 端口,https 對應 443 端口。一般在雲平台租的服務器,可以在控制台中的防火牆處開啟相應端口。我的設置可供參考。

服務器端口

接下來啟動 Nginx

systemctl start nginx

啟動成功後,瀏覽器搜索服務器 IP 地址,就能訪問到 Nginx 主頁了。

Nginx 默認主頁

部署項目

上傳項目

Django 後端項目文件,直接上傳至服務器即可。Vue 框架寫的前端,需要使用 npm run build 命令進行打包,再將生成的 dist 目錄上傳。

這裡推薦軟件 FileZilla,用於本地與服務器文件傳輸十分方便。

配置 uWSGI

新建文件 uwsgi.ini,我習慣放置於 Django 項目的根目錄下,用於指定項目路徑、最大進程數、運行端口等。我的配置參數可供參考。

[uwsgi]
socket = 127.0.0.1:8080
chdir = /root/Ops/django
wsgi-file = /root/Ops/django/django3/wsgi.py
master = true 
enable-threads = true
processes = 8
buffer-size = 65536
vacuum = true
daemonize = /root/Ops/django/uwsgi.log
virtualenv = /root/.virtualenvs/django
uwsgi_read_timeout = 600
threads = 4
chmod-socket = 664

簡要介紹該文件的配置信息:

  • [uwsgi]:必須有這個[uwsgi],不然會報錯
  • socket:該端口為後端 Django 的運行端口,可自定義,但須與後面 Nginx 的配置一致
  • chdir:django 項目路徑
  • wsgi-file:django 項目的 wsgi.py 文件路徑
  • master:開啟主進程
  • processes:最大進程數量
  • vacuum:當服務器退出的時候自動刪除 unix socket 文件和 pid 文件
  • daemonize:輸出日誌,有報錯時可查看
  • virtualenv:項目虛擬環境路徑

切換當前路徑到 uwsgi.ini 文件所在目錄,啟動 uWSGI。

uwsgi --ini uwsgi.ini

使用 ps 命令查看進程,檢測是否成功。

ps -aux | grep uwsgi

uwsgi 進程查看

配置 Nginx

這裡我部署的是域名而非IP,IP配置與域名的區別在於,不需要SSL證書字段。

首先,刪除 /etc/nginx/nginx.conf 文件中 server{...} 部分的代碼。當然,如果怕出錯,也可先將原本的 nginx.conf 文件備份一下。

接下來,在 /etc/nginx/conf.d 文件夾中修改默認文件 default.conf(若不存在則新建一個),文件內容如下:

server {
    listen 80;
    listen 443 ssl;
    server_name  zewan.top www.zewan.top;

    location / {
        root /root/Ops/vue/dist;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /api {        
        include /etc/nginx/uwsgi_params;
        uwsgi_pass 127.0.0.1:8080;                                                               
    }

    ssl_certificate /etc/nginx/ssl/zewan.top.crt;
    ssl_certificate_key /etc/nginx/ssl/zewan.top.key;
    ssl_session_timeout  5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4:!DH:!DHE;
    ssl_prefer_server_ciphers  on;

    error_page 497  //$host$uri?$args;
}

簡要說明文件內容的作用:

  • listen 後接端口,即設定訪問的端口,此處同時開放 80 和 443
  • server_name 為訪問域名
  • location / 後描述前端 dist 項目文件夾的存放地址,需根據自身情況修改,注意 dist 即為前端項目的根目錄
  • location /api 後為後端項目運行端口,注意 uwsgi_pass 後須與之前 uWSGI 的配置保持一致
  • ssl_certificate[_key] 為 SSL 證書存儲路徑

重要提醒

採用 location /api 與 uWSGI 連接,最終將後端運行在 :443/api/。需保證後端的路由都是 api/*,即 Django 項目的 urls.py 文件所有路由前需加 api/

運行項目

檢測 Nginx 配置是否有誤,成功後重啟 Nginx 服務。

nginx -t                # 測試
nginx -s reload         # 重新加載

注意,若修改了後端 Django 內容或其它內容,須重啟 uWSGI 和 Nginx 服務,否則不生效!

ps -ef | grep uwsgi         # 查看uWSGI進程
killall -9 uwsgi            # 用kill方法把uwsgi進程殺死
uwsgi --ini uwsgi.ini       # 重啟uwsgi
nginx -s reload             # nginx平滑重啟

另外,如果你的項目文件存放於 root 用戶目錄下,訪問網站時可能出現 500 或 403 Forbidden 權限報錯,此時需修改 /etc/nginx/nginx.conf,將文件首行的 user nginx 修改為 user root

至此網站已部署完畢。項目問卷系統已開源,歡迎交流學習!