1. 程式人生 > >在Linux上從零開始部署前後端分離的Vue+Spring boot專案

在Linux上從零開始部署前後端分離的Vue+Spring boot專案

最近做了一個前後端分離的商城專案來熟悉開發的整個流程,最後希望能有個正式的部署流程,於是試著把專案放在雲伺服器上,做了一下發現遇到了不少問題,藉此記錄一下整個部署的過程。 使用的技術棧如標題所說大體上是Vue+Spring boot,但還是要提一下詳細的版本,因為在解決問題的過程中發現由於開發環境的不同會產生諸多影響,查詢問題時如果沒有版本作為前提經常會出現很多不必要的誤解,甚至是誤操作,非常浪費時間。詳細版本情況如下: - Vue 2.6.11 - Vue-cli 4.5.0 - Spring boot 2.1.1 - MySQL 8.0.13 (尤其注意) - Nginx ## 1 上傳工具 部署的第一步要把檔案上傳至雲伺服器,並且後續還要在雲伺服器上進行操作,方法很多,我這裡選擇了Xshell和Xftp這兩個工具,均出自NETSARANG這家公司,需要注意的是在國內的官網上隱藏了免費家庭版的申請地址,可以通過直接訪問 [Xshell、Xftp免費許可](https://www.netsarang.com/zh/free-for-home-school/) 進行下載,需要填寫姓名和郵箱。 ### 1.1 Xftp 首先在Xftp中新建連線,填寫主機地址和使用者名稱密碼,連線成功就可以看到左側選項卡為本地的檔案目錄,右側為雲伺服器的檔案目錄,只要從左側或右側將檔案拖動到另一邊就可以實現相應檔案的上傳和下載,下方傳輸選項卡會顯示具體進度,圖形化的介面相當直觀,不做過多的說明了。 ![](https://i.loli.net/2021/03/05/er1kHOZnSBGtKjq.png) ![](https://i.loli.net/2021/03/05/NYLfRTQ7hO8JmPW.png) 關於Linux的目錄規範我沒有查到太多需要的資訊,所以我這裡是在根目錄新建了一個名為 **app** 的資料夾來存放網站應用,關於網站的打包我們在下一節說明,這裡我們掌握如何上傳檔案就可以。 ### 1.2 Xshell Xshell的連線建立方法與Xftp差不多,填寫主機地址,連線後再輸入使用者名稱密碼,連線後就可以在雲伺服器上進行操作了。 ![](https://i.loli.net/2021/03/05/P9aIkOpMStYuBf4.png) ![](https://i.loli.net/2021/03/05/oYAz8mKQG2averh.png) 通過這兩個工具與雲伺服器建立聯絡後我們就可以開始著眼於網站應用自身的問題了。 ## 2 前端 相對來說前端的部署沒有遇到太多問題,所以我們先從前端開始 ### 2.1 Vue 由於我使用了Vue-cli,所以專案完成後通過執行命令 `npm run build` 程式就會自動打包到專案目錄下的 **dist** 資料夾,打包後的目錄結構如下: ![](https://i.loli.net/2021/02/06/DMv5Ek4eC6FbgYy.png) 之後通過Xftp將這個資料夾上傳至雲伺服器上,之前我已經新建了一個資料夾來存放,因為我們還可能有其他專案,並且後臺也需要一個資料夾,所以建立具體資料夾結構如下: ![](https://i.loli.net/2021/03/05/UtFRmoTXHgsY6SP.png) 新建資料夾可以使用Xftp的圖形介面快速建立,也可以在Xshell中使用指令,看個人的喜好和習慣,如果需要經常使用Linux系統,建議使用指令多加練習。 在Windows端進行開發的時候,在控制檯使用 `npm run serve` 指令就可以快速啟動一個本地網站,但是這樣的網站只能在內網被訪問,肯定是達不到我們最初在外網訪問的目的,所以這裡要藉助反向代理伺服器,我選擇的是被廣泛使用的Nginx。 ### 2.2 Nginx 1. 選定安裝目錄 ``` shell cd /usr/local/src ``` ![](https://i.loli.net/2021/03/05/bJDRgdvrkW6i1Ql.png) 2. 在伺服器上安裝Nginx之前先安裝若干依賴: ``` shell yum install gcc yum install pcre-devel yum install zlib zlib-devel yum install openssl openssl-devel ``` 這些依賴的作用可以參考這一篇 [Linux上安裝Nginx依賴環境和庫、Nginx安裝,Nginx服務命令](https://www.cnblogs.com/dreamyy/p/11135872.html),我沒有逐一試過缺少某個依賴會有什麼問題,在安裝Nginx之前就已經安裝好這些依賴了。 3. 下載Nginx安裝包並解壓 可以從官網選擇需要的版本。 ``` shell wget http://nginx.org/download/nginx-1.13.7.tar.gz #下載 tar -xvf nginx-1.13.7.tar.gz #解壓 ``` 4. 執行配置並安裝 ``` shell cd nginx-1.13.7 #切換目錄 ./configure #執行配置 make && make install #編譯安裝(預設安裝在/usr/local/nginx) ``` 5. 安裝完成後檢視版本無誤啟動 ``` shell /usr/local/nginx/sbin/nginx -v #檢視版本 cd /usr/local/nginx/sbin #cd到nginx的安裝位置的sbin目錄下 ./nginx #啟動nginx ``` 這裡可以先訪問一下伺服器的外網IP試試,出現 **Welcome to nginx** 就說明已經啟動成功了。 Nginx安裝完成後修改配置檔案以對應我們的網站應用,修改檔案的方法也可以選擇使用Xftp或者在Linux上用指令操作 ``` location / { root /app/osd_mall/vue_app/dist; index index.html index.htm; } location /api { proxy_pass http://localhost:28019/api/v1; } ``` 這裡映射了兩個地址,第一個就是網站前端部分的主體,應該沒有太多的差異,主要的問題應該集中在第二個地址上,由於我做的是一個前後端分離的專案,後端介面也是包含在專案裡的,那麼必然存在跨域問題,開發時使用了Vue的Proxy從前端處理,程式碼如下: ![](https://i.loli.net/2021/03/05/zJEFRsUYnDSNQOf.png) 然後在axios裡配置對應的名稱即 **api**,這樣就可以解決跨域的問題,但這只是本地開發時使用的方法,在Linux伺服器上通過Nginx反向代理可以更安全地處理跨域問題,所以上圖中的程式碼就不再需要了,打包前需要註釋或者刪除。 ``` json axios.defaults.baseURL = process.env.NODE_ENV == 'development' ? '/api' : '/api' ``` ![](https://i.loli.net/2021/03/05/exN1gPuczMItf7O.png) 配置修改完成後測試配置檔案,沒有問題後重啟Nginx服務 ``` shell ./nginx -t #測試配置檔案 ./nginx -s reload #重啟Nginx ``` 這時已經可以通過我們的外網IP訪問前端頁面了,但是由於還沒有配置後端介面,所以基本是沒有資料和圖片的。顯而易見,上圖中的本地地址 http://localhost:28019/api/v1 就是我們的後端介面地址,那麼我們接下來就對後端的部署進行說明。 ## 3 後端 相對於前端來說,後端遇到的問題可謂是層出不窮,中間有很多波折,好在最後都解決了,其中有幾個就是開頭強調的版本問題。 ### 3.1 Java 首先要安裝Java環境,從官網下載需要的版本,然後和之前一樣,通過Xftp上傳: ![](https://i.loli.net/2021/03/05/Vn1suCq2d7UjYyg.png) 建立目錄,解壓: ``` shell mkdir /usr/java tar zvxf server-jre-8u271-linux-x64.tar.tar.gz -C /usr/java ``` 為了能在全域性使用java命令,配置環境變數: ``` shell # 修改環境配置檔案 vi /etc/profile # 編輯配置檔案,在裡面新增如下三行 export JAVA_HOME=/usr/java/jdk1.8.0_271 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar # 使環境變數生效 source /etc/profile # 驗證是否配置成功,檢視java版本 java -version ``` ![](https://i.loli.net/2021/03/05/7yraGNpOlX48ADe.png) ### 3.2 Spring boot 要將Spring boot專案打包部署有很多選擇,詳情可以看這篇文章 [java專案部署Linux伺服器幾種啟動方式總結經驗](https://www.cnblogs.com/both-eyes/p/12221946.html) 我這裡選擇的是使用jar包部署,通過Maven打包的步驟就不說明了。再次通過Xftp將jar檔案上傳至伺服器,我的截圖裡有一個dev版本的是保留了控制檯日誌的版本,正常只需要一個就可以。 ![](https://i.loli.net/2021/03/05/rLi4fGbK9ZCSXmg.png) ### 3.3 Screen 上面介紹的文章裡有提到java專案會執行在前臺,當我們的Xshell視窗關閉後,專案其實也是會關閉的,但如果讓連入的機器也保持開機也並不合理,所以使用nohub指令將jar程式一直掛載在後臺。這裡再介紹另一種方法,那就是Screen工具。 > **Screen**是一款由GNU計劃開發的用於命令列終端切換的自由軟體。使用者可以通過該軟體同時連線多個本地或遠端的命令列會話,並在其間自由切換。GNU Screen可以看作是視窗管理器的命令列介面版本。它提供了統一的管理多個會話的介面和相應的功能。 Screen在一些流行的發行版上已經預安裝了,你可以使用下面的命令檢查是否已經在你的伺服器上安裝了。 ``` shell screen -v ``` 如果沒有可以通過自帶的包管理器簡單地安裝。 ``` shell yum -y install screen ``` ``` shell screen -S yourname #建立一個名為yourname的session screen -ls #列出當前所有的session screen -r yourname #回到yourname這個session screen -d yourname #遠端detach某個session screen -d -r yourname #結束當前session並回到yourname這個session ``` 使用Screen就如同切換視窗一般,這樣在伺服器效能允許的情況下就可以同時掛載多個應用,同時也相對方便管理。 ### 3.4 MySQL #### 1. 安裝 剛開始部署的時候,我幾乎忽略了MySQL,之後也沒想到這是最花時間的部分,但如果遵循正確的步驟其實並不困難。 大部分的工具我們都可以通過包管理器yum來安裝,上文的Screen正是如此,我本以為MySQL也是如此,不過查了一下發現最初確實如此,但自從MySQL被收購之後就存在版權問題了,所以CentOS7已經不再支援MySQL,而是在內部集成了MariaDB,兩者頗有淵源,結果就是檔案會有衝突,所以還要先解除安裝MariaDB才行。 ``` shell # 列出所有被安裝的rpm package rpm -qa | grep mariadb # 解除安裝(注意“版本號”根據當前系統顯示的版本資訊的為準) rpm -e mariadb-libs-5.5.37-1.el7_0.x86_64 # 如果提示依賴檢測失敗可以強制解除安裝 rpm -e --nodeps mariadb-libs-5.5.37-1.el7_0.x86_64 # 安裝依賴 yum install vim libaio net-tools ``` 之後我們要決定是通過repo源直接從伺服器下載安裝還是自己去官網下載一個再上傳到伺服器上,最初我是按一些教程的步驟直接從repo源下載,但由於選擇的版本不對,最後程式無法正確建立連線,反覆嘗試之後選擇從[社群版官網](https://dev.mysql.com/downloads/mysql/)下載需要的版本。 ![](https://i.loli.net/2021/03/05/McDyfszhUXn1iJS.png) 進入網站預設是最新版本,要找之前的版本點選Archives,在新的頁面選擇對應的版本。然後是選擇作業系統,CentOS系統就是Red Hat的社群發行版,核心是相同的,或者用通用版本(Generic)也可以。 ![](https://i.loli.net/2021/03/05/ruslDmGpLa6cYPH.png) 下載bundle包,解壓出其中如圖所示的五個檔案上傳至伺服器,依次安裝mysql-community-common、mysql-community-libs、mysql-community-client、mysql-community-server、mysql-community-release。 ``` shell # 依次類推 rpm -ivh mysql-community-common-8.0.13-1.el7.x86_64.rpm # 如果出現“依賴檢測失敗”問題再後面新增 --force --nodeps強制安裝 rpm -ivh mysql-community-common-8.0.13-1.el7.x86_64.rpm --force --nodeps ``` 現在常見的MySQL版本一般是5.7和8.0之後的若干小版本,根據使用版本的不同,後續的配置有很大的不同,我使用的版本是8.0.13,接下來也是以8.0版本為例。 #### 2. 重置密碼 在這一步遇到了諸如許可權問題、版本不對、欄位不同等情況,因為部署時完全沒想到有如此多的問題,沒有留下截圖,這裡說一下整體的思路:首先要登入MySQL,安裝完成後可能會有一個隨機密碼,記錄下來,用這個密碼登入進資料庫,如果有許可權問題就先給MySQL資料夾授權,登入之後通過資料表修改預設密碼,指令如下: ``` shell # 登入,-p後面沒有空格,直接輸入密碼,5.7版本密碼預設為空,8.0使用隨機密碼 mysql -u root -p密碼 # 切換資料庫 use mysql; # 修改密碼(不能用123456這種簡單的密碼,需要大小寫和數字,如果還是想用簡單的密碼,看下文) update user set password=password('123456') where user='root'; # 退出 exit; ``` 設定完成後就可以用新密碼登入了,如果設定有問題或者沒有記錄隨機密碼還有通過修改本地檔案來重置密碼的方式,這裡就不介紹了。 如果只是個人開發,不想用太過複雜的密碼怎麼辦?可以通過修改密碼規則來解決這一問題,同樣的,5.7和8.0版本也存在區別: ``` shell # 5.7 set global validate_password_policy=0; set global validate_password_length=1; # 8.0 set global validate_password.policy=0; set global validate_password.length=1; # 檢視密碼驗證變數 SHOW VARIABLES LIKE 'validate_password%'; ``` 密碼等級表 | Policy | Tests Performed | | :------------- | :------------- | | 0 or LOW | Length | | 1 or MEDIUM | Length; numeric, lowercase/uppercase, and special characters | | 2 or STRONG | Length; numeric, lowercase/uppercase, and special characters; dictionary file | #### 3. 遠端連線 每次要查資料庫都要登入Linux就會很不方便,而且介面不友好,如果我們想用本地的Navicat訪問遠端的資料庫要怎麼設定呢? 首先要關閉防火牆或者開放資料庫的3306埠(最好還是開放埠), ``` shell # 檢視防火牆狀態 systemctl status firewalld # 開啟防火牆服務 systemctl start firewalld # 開放指定埠 firewall-cmd --zone=public --add-port=3306/tcp --permanent # 重新載入 firewall-cmd --reload ``` 如果使用的是雲伺服器,還要記得在平臺上開放指定埠: ![](https://i.loli.net/2021/03/05/4kQzWX5GYeZRtVU.png) 設定完防火牆之後仍然不能遠端登入,因為我們沒有授權使用者,先查詢一下使用者表: ``` sql select user,host from user; ``` ![](https://i.loli.net/2021/03/05/oXEKUj7lcNgaLxT.png) 可以看到除了remote都是localhost,remote就是我新建的專門用於遠端登入的使用者,host代表的是該使用者可以在哪個地址下登入,“%”代表所有地址都可以。5.7之前的版本可以通過授權直接隱式建立使用者,8.0之後不可以了。直接修改root使用者的host也是可以的,但是這樣登入時會有些小區別,具體忘記了,這裡我推薦新建一個使用者。 ``` sql /* 建立使用者,這裡的密碼同樣也受前面設定的密碼等級限制 */ CREATE USER '使用者名稱'@'%' IDENTIFIED BY '密碼'; /* 授權 */ grant all privileges on *.* to '使用者名稱'@'%'; ``` 執行後使用Navicat遠端登入如果報錯 **1251 client does not support authentication**,說明MySQL8與Navicat的加密方式不同,修改加密方式: ``` sql alter user 使用者名稱 identified with mysql_native_password by '密碼'; ``` 這樣就可以從本地直接訪問遠端的資料庫了。 #### 4.解除安裝MySQL 如果你在安裝時不幸出現問題,有各種各樣的問題需要重灌MySQL,那麼可以根據這篇文章 [Linux下徹底解除安裝mysql詳解](https://www.cnblogs.com/nicknailo/articles/8563456.html)來解除安裝MySQL。 #### 5.程式建立資料庫連線 到這裡就是最後一步了,我在這裡出現問題後試了各種方法都沒有成功建立連線,使用者名稱密碼都沒有錯的情況下可能需要檢查以下幾個方面: - 資料庫版本與程式的驅動版本是否一致 - 資料庫連線串是否正確 - 賬號是否有訪問許可權 引用的外掛版本要與伺服器上安裝的資料庫版本一致 ![](https://i.loli.net/2021/03/05/nAqVExNPDMQeRuS.png) 5.7和8.0的連線串有不少區別,8.0需要很多額外詞條,這裡留下我的連線串 ``` jdbc:mysql://localhost:3306/onesideddice_mall?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&allowPublicKeyRetrieval=true&useSSL=false&allowMultiQueries=true ``` #### 6.匯入資料 這一步很簡單了,有各種方法,這裡記錄一下匯入伺服器上的sql檔案這種方式: ``` sql create database abc; /* 建立資料庫 */ use abc; /* 使用已建立的資料庫 */ set names utf8; /* 設定編碼 */ source /home/abc/abc.sql /* 匯入備份資料庫 */ ``` ### 3.5 Nginx圖片伺服器 在前端部分我們已經在Nginx中配置過後端介面了,為什麼這裡還要再提一次呢?其實理論上到這一步之前,就已經完成網站的部署了,如果中間各種對接沒有其他問題,網站已經可以正常運行了,但是如果你的站點中有大量的圖片,則不得不思考圖片要以什麼方式儲存,相對路徑如何設定等。在部署完成後在圖片展示上我遇到了很多問題,其中比較顯著的就是圖片的相對路徑轉換問題,在觀察了一些網站的後,我發現他們的圖片通常單獨存放在圖片伺服器上,這樣圖片的路徑相對穩定又方便設定,於是我就想到用Nginx再配置一個圖片伺服器出來,儘可能地利用現有的伺服器資源,當然也可以選擇七牛雲這種專門的圖片伺服器,這樣圖片的訪問應該會更加穩定快速。 1. 配置Nginx 在Nginx的配置裡新增一個新的Server,方便與我們的網站應用區分,配置如下: ``` server { listen 8000; server_name localhost; location / { root /app/osd_mall/images; autoindex on; } } ``` - root則是將images對映到/home/ftpadmin/hatlth/images/ - autoindex on便是開啟瀏覽功能。 設定修改完成後記得測試並重載Nginx。 2. 開放埠 和之前開放資料庫埠相同。 ![](https://i.loli.net/2021/03/05/kTsaFJg3hPtN9M1.png) 3. 修改檔案訪問許可權 ``` shell chown ftpadmin /app/osd_mall/images chmod 777 -R /app/osd_mall/images ``` 4. 修改程式 根據自己的站點修改路徑,由於使用了統一的圖片伺服器,現在可以設定一個配置項來專門管理圖片地址了,相對於之前要方便很多,本地環境也可以使用這個線上的圖片伺服器。 ## 4 結束 到這裡,基本的部署就完成了,實現了從本地Windows端到Linux服務端的轉換,在解決問題的過程中沒有想到有如此多的問題,記錄的時候遺漏了很多細節,但主要的問題應該都得以解決,希望能幫助遇到問題的人,也方便自己日後回顧