Django + react + 阿里雲ecs 前後端分離部署上線

張白臺發表於2018-12-24

背景

因為之前一直在搗鼓Python,本人是前端菜鳥一枚~,一直想著做個小demo,把後端和前端給統一跑起來,正好也可以把掌握的知識梳理一遍,這樣前端後端就能夠打通,豈不快哉!平時上班大家都知道沒時間幹別的,乘著這兩天週末,決定把之前搭好的開發環境,給弄到線上去,其實開發環境也搞了一兩天,因為django的csrf的坑,還有就是因為前後端要分離嗎,還要搭建前端開發環境。前端是webapck + react + react-router + mobx + axios + antd,後端是django + mysql + uwsgi + nginx,這是我第一次部署,所以踩了很多坑,包括阿里雲也是第一次使用,希望給別的小夥伴一個參考,要是能在這邊文章中解決問題,那就開心了,廢話不多說,開始正題。

環境準備

首先你要有一臺線上伺服器,先配好服務端的環境,我用的是阿里雲的ECS伺服器,Linux Ubuntu16.04版本。系統不一樣可能下面需要安裝的軟體依賴也會不同,不過大同小異。不是什麼大不了的。登入阿里雲控制檯,找到伺服器例項

Django + react + 阿里雲ecs 前後端分離部署上線
點選遠端連結,然後會跳到遠端連結頁面,頁面會有一個彈框,輸入遠端連結密碼,這個密碼要記下來,後面登入時會一直使用。登入後的介面

Django + react + 阿里雲ecs 前後端分離部署上線
強烈建議不要使用這個終端,因為太坑,你只能通過clear命令清屏,不能上下翻屏,也不能回滾。。。建議使用ssh命令在本地遠端登入: ssh 使用者名稱@ip地址 使用者名稱是你伺服器上的使用者名稱,ip地址是你伺服器上的公網ip,新買來的伺服器預設只有root使用者名稱(第一次使用一臉懵逼,就在想這TM使用者名稱是啥我怎麼駕馭它。。笨的要死),建議不要用root賬戶操作,useradd 使用者名稱 新建一個使用者名稱,然後新增sudo許可權,這個很重要哦,不然很多命令沒有許可權,關於Ubuntu命令自行百度啦。為伺服器新增安全組,後面專案會用到埠號,新增22、3306、8080等,用到什麼埠加新增什麼埠,這裡也是一顆坑,不然專案根本無法訪問。

  • 安裝依賴 當新增好新的賬戶後,後面所有的操作都將在這個賬戶下操作了。安裝nginx sudo apt-get install nginx這是我用的版本。可能會有別的提示,這是因為需要更新映象,sudo apt-get update然後在下載應該就可以了,nginx用於與uwsgi配合做請求轉發。下載好的nginx的預設路徑在 /etc/nginx 這個目錄,網上有人說在/usr/local/nginx,這個看具體的環境吧,我覺得這種情況可能是因為安裝的方式不同造成的,我是直接install的,網上有的是下載.tar壓縮包然後在解壓,這樣可能就會造成nginx的安裝路徑不同。

  • 然後啟動nginx sudo service nginx start 在瀏覽器中輸入ip地址,如果顯示wenlcome....證明nginx正常。如果nginx沒有效果,使用此命令systemctl status nginx.service,可以檢視具體報錯資訊。接著安裝mysql,sudo apt-get install mysql-server 啟動服務sudo service mysql start 檢視程式ps ajx|grep mysql 停止服務sudo service mysql stop 重啟服務sudo service mysql restart配置mysql進入/etc/mysql/mysql.cnf.d sudo vim mysql.cnf找到bind-address表示伺服器繫結的ip,預設為127.0.0.1,把ip地址改為伺服器的IP。安裝過程中會讓你輸入密碼這個設定下就好,一會用於登入,接著安裝mysql客戶端sudo apt-get install mysql-client 客戶端安裝完,就可以登入賬戶了,通過mysql -uroot -pxxxxxx,預設只有root賬戶,登陸後新增mysql使用者,並設定密碼和許可權如:grant select on 資料庫.表 to 'laowang'@'localhost' identified by '123456';具體自行百度吧,設定好後這是用於django專案線上上操作mysql資料庫時要用的使用者名稱和密碼等,注意許可權的問題,這裡也是容易犯錯的地方!

  • 安裝python虛擬環境,這個虛擬環境很多人開發不一定能用到沒有用到的請跳過吧,不過還是建議使用,因為很方便管理維護專案,伺服器自帶的python版本有2.7和3.5,所以不用安裝Python

sudo pip install virtualenv #安裝虛擬環境
sudo pip install virtualenvwrapper #安裝虛擬環境擴充套件包
編輯家目錄下面的.bashrc檔案,新增下面兩行。
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
使用source .bashrc使其生效一下。
建立虛擬環境命令:
	mkvirtualenv 虛擬環境名
建立python3虛擬環境:
mkvirtualenv -p python3 name


進入虛擬環境工作:
	workon 虛擬環境名
檢視機器上有多少個虛擬環境:
	workon 空格 + 兩個tab鍵
退出虛擬環境:
	deactivate
刪除虛擬環境:
	rmvirtualenv 虛擬環境名
虛擬環境下安裝包的命令:
pip install 包名
注意:不能使用sudo pip install 包名,這個命令會把包安裝到真實的主機環境上而不是安裝到虛擬環境中。
apt-get install 軟體
pip install python包名
複製程式碼

虛擬環境主要是用於隔離專案依賴的版本,多個專案互相不影響

現在進入你本地開發好的專案根目錄,執行pip freeze > list.txt這是匯出你這個專案所依賴的全部包,一會要在伺服器上的虛擬環境下載這些包,本地通過ssh 命令連結伺服器,然後通過scr -r 命令把本地專案上傳到伺服器,上傳前記得把專案的settings.py這個檔案配置檔案的ALLOWED_HOSTS = ['*',]或者寫你的伺服器ip, DEBUG = False這個要新建一個資料夾。比如/home/abc/wwwroot/ abc是你伺服器當前的賬戶名,切換到虛擬環境,進入專案然後pip install -r list.txt下載依賴。這個時候你可以通過python3 manage.py runserver 跑起你的專案,看是否正常,如果一切正常,說明環境什麼的都是OK的,中間如果有什麼不對,缺什麼下載什麼.

  • 接著安裝uwsgi,切換虛擬環境,pip install uwsgi,在這個過程中可能會出錯,這是因為系統缺少依賴,另外就是所用的python版本造成的,我用的是3.5的版本,然而系統好像預設是2.7。比如這些libpcre3 libpcre3-dev zlib1g-dev openssl libssl-dev python3-dev python-dev,缺什麼下載什麼,可以通過dpkg -l | grep zlib這個命令檢視系統是否有對應的依賴,然後通過sudo apt-get install 下載。 進入專案根目錄,sudo vim uwsgi.ini 檔案叫什麼名字無所謂,然後加上下面內容
[uwsgi]
#使用nginx連線時使用
#socket=127.0.0.1:8080
#直接做web伺服器使用
http=127.0.0.1:8080
#專案目錄
chdir=xxxxxxx
#專案中wsgi.py檔案的目錄,相對於專案目錄
wsgi-file=xxxxxx
processes=4
threads=2
master=True
pidfile=uwsgi.pid
daemonize=uwsgi.log
#virtualenv=xxxxx


複製程式碼

這是我的配置,可以看到下面有一個home和virtualenv配置它們的路徑是一樣的,效果卻不一樣如果我用virtualenv它就跑不起來,用home就可以,這個坑踩了好長時間。。。都是淚,它們視乎都是使用者虛擬環境的配置,有空在查下資料它們的區別。

Django + react + 阿里雲ecs 前後端分離部署上線
進行到這一步,上面我用的是socket的連結,這是和nginx配合使用的,這個不急一會再說,現在先把socket註釋掉,把http開啟,後面的埠號根據自己專案來定。然後儲存退出編輯,通過命令,此時所在的目錄是專案根目錄,uwsgi --ini uwsgi.ini 啟動uwsgi服務,這個時候就不用python3 manage.py runserver了,uwsgi就可以充當web伺服器,這樣是檢驗當前的配置依賴,一切是否都正常,啟動後,可以在瀏覽器中輸入IP地址加埠號以及你配置的urls的路徑,看是否返回正常,注意這個時候是測試,所有請用get請求,不要用post 因為post有csrf的問題。或者直接在命令列中輸入python3,進入python執行環境,import requests 然後requests.get('127.0.0.1:8888/xxxx')檢視返回狀態。若是ok那麼到目前一切正常,如果有錯誤 請檢視專案根目錄下面生成的uwsgi.log日誌檔案,檢視日誌檔案,是解決問題的最好辦法。如果沒問題,就把socket開啟,http註釋掉,下面要把nginx和uwsgi結合起來。

  • 再次之前把通過webapck打包好的前端dist資料夾上傳到伺服器,位置應該沒有影響,我放在nginx的目錄下面了。找到nginx目錄,/etc/nginx/nginx.conf:
	server {
		listen       80;
		server_name  localhost;

		#charset koi8-r;

		#access_log  logs/host.access.log  main;

		#location / {
		#    root   html;
		#    index  index.html index.htm;
		#}
	        # root  /etc/nginx/dist; 		
	       location / { 
			
		           add_header 'Access-Control-Allow-Origin' '*'; 
                           add_header 'Access-Control-Allow-Credentials' 'true';
                           add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
                           add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
                           root  /etc/nginx/dist;      #"這裡就要指定你的前端目錄檔案了,也就是剛剛放進nginx根目錄的資料夾"
                           index html index.html;     #"build 目錄下預設有index.html 指定預設檔案"
                           try_files $uri /index.html;   #"這塊分重要,曾經不加嘗試過,當我訪問login路徑時,他不會自動跳轉,具體自行百度"
	                   #error_page 405 =200 $uri; 
		}
               location  ~ /api/* {#這個是前端ajxa的請求地址,比如33.66.0.1:8888/api/register,都會轉發給django後端,這個和開發環境還是有區別的,前端可以通過webpack的devserver做轉發,所有後端的地址在上線時,要注意和這個設定的路由要匹配
                           include uwsgi_params;
                           uwsgi_pass 127.0.0.1:8888; 
               }
	    #這個是你通過webpack打包後的html頁面載入的檔案路徑
		location /static {
			# 指定靜態檔案存放的目錄
			alias /etc/nginx/dist/;	
		#	root /home/zjp/wwwroot/dist;
		#        index index.html index.html;
                #        try_files $uri /index.html;
		}

		#location = / {
		#	proxy_pass http://172.16.179.131;	
		#}
		#error_page  404              /404.html;

		# redirect server error pages to the static page /50x.html
		#
		error_page   500 502 503 504  /50x.html;
		location = /50x.html {
		    root   html;
		}

		# proxy the PHP scripts to Apache listening on 127.0.0.1:80
		#
		#location ~ \.php$ {
		#    proxy_pass   http://127.0.0.1;
		#}

		# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
		#
		#location ~ \.php$ {
		#    root           html;
		#    fastcgi_pass   127.0.0.1:9000;
		#    fastcgi_index  index.php;
		#    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
		#    include        fastcgi_params;
		#}

		# deny access to .htaccess files, if Apache's document root
		# concurs with nginx's one
		#
		#location ~ /\.ht {
		#    deny  all;
		#}
      }
複製程式碼

這裡面一個坑就是要把#include /etc/nginx/conf.d/*.conf; #include /etc/nginx/sites-enabled/*;註釋掉,因為當訪問80埠的時候,會預設把/var/www/html/下的檔案給你返回,這樣你自己的靜態檔案就無法顯示,這是因為裡面有預設的配置。更多nginx的配置自行百度。接下來就是收集django所依賴的靜態檔案了,因為是前後端分離的專案,所以django所需要的靜態檔案並不多,需要在伺服器上新建一個資料夾,來存放所收集的靜態檔案,然後記住這個路徑,在專案的settings.py的加上:

STATIC_ROOT = '/var/www/reactObject/static/'

複製程式碼

儲存,提醒:這時候還要注意mysql的配置,因為現在是線上環境了,所以settings檔案中的資料庫的賬戶也要記得修改。然後執行python manage.py collectstatic,就會把檔案存放在STATIC_ROOT這個指定的目錄下,然後在上面的nginx的目錄中配置對應的路由。因為我的這個專案靜態檔案都在前端,所以我收集的時候,沒有檔案。也就沒有配置對應的路由。

另外在我配置nginx和uwsgi的時候,我在網上看到一個小夥伴說要把下面紅色的檔案

Django + react + 阿里雲ecs 前後端分離部署上線
放在專案根目錄的下面,我信你個鬼,你這糟老頭子壞的很~ 我把它放在了專案目錄的下面怎麼都跑不起來,又是檢查各種配置是否有誤,檢查log檔案等。。。都是淚不說了,後來也看了別人的部落格,發現根本沒有這個檔案,而且這個檔案都是預設安裝的,不需要動它。

到了這一步基本配置都差不多結束了。重新啟動nginx 和uwsgi。這個時候你在瀏覽器中輸入IP地址加埠號,沒問題的話就可以出來頁面了。

如果你有域名的話,可以把域名跟伺服器繫結,通過域名解析就可以啦~我的小demo,當我看見頁面完完整整出來的時候,心裡真是太爽了!這裡面其實有很多可以優化的地方,後面再說,先跑通才是最要緊,覺得不錯給個贊吧

相關文章