teprunner測試平台部署到Linux系統Docker
本文是一篇過渡,在進行用例管理模組開發之前,有必要把入門篇開發完成的程式碼部署到Linux系統Docker中,把部署流程走一遍,這個過程對後端設計有決定性影響。
本地運行
通過在Vue項目執行npm run serve
和在Django項目執行python manage.py runserver
,我們把項目在本地跑起來了,示意圖如下:
前端在本地啟了個Node伺服器,後端在本地啟了個Django伺服器,分別使用8080
和8000
埠。瀏覽器有個同源策略:域名、埠、協議三者一致才能進行訪問,否則會由於跨域訪問而被瀏覽器攔截。圖中前後端的埠不一致,出現了跨域,前端是無法直接請求後端的。解決辦法是在vue.config.js
中配置devServer
:
這是Node開的一個代理伺服器,當前端請求後端時,會先發向Node代理伺服器,Node代理伺服器以相同的參數向真正的後端伺服器進行請求,再把響應返回給前端。在本項目中,前端請求仍然是發給//127.0.0.1:8080
,瀏覽器不會攔截,Node代理伺服器會幫你把請求轉發給後端8000
埠。
Nginx部署
搞懂了本地運行代理轉發,再來看看Nginx部署。Nginx本身是個伺服器,就像Node伺服器一樣,也可以看做Apache Tomcat。Vue項目使用npm run build
命令把程式碼構建為dist
目錄靜態文件,放到Nginx伺服器中載入出來,結合Docker示意圖如下:
相比於本地運行,Nginx部署時,前端變化比較大,一:dist
靜態文件拷貝到了/usr/share/nginx/html
目錄中,二:對/
路徑來說,Nginx會監聽80
埠,三:對/api
路徑來說,Nginx會把請求轉發到後端伺服器埠,這也叫做反向代理。後端沒有什麼變化,為了和本地運行看著有點區別,把埠稍微改了下,Docker內部使用80
埠。
這裡比較關鍵的是理解Docker teprunner-frontend
、Docker teprunner-backend
、Linux
三者之間的關係。如果不知道Docker,那麼應該聽說過虛擬機,Docker從概念上理解就像是虛擬機,這三者可以看做是三台主機。Linux
的IP是172.16.25.131
,80
埠映射到了Docker teprunner-frontend
的80
埠,8099
埠映射到了Docker teprunner-backend
的80
埠,如圖中下方雙向箭頭所示。在Linux
上訪問//127.0.0.1
,能打開登錄頁面,但是無法向後端發起請求,因為從80
埠直接請求8099
埠,跨域了。解決辦法是在Docker teprunner-frontend
藉助Nginx進行反向代理,把請求先發送到Nginx伺服器,再轉發給Linux
的8099
埠。
不能在
Docker teprunner-frontend
中把/api
的代理設置為//127.0.0.1:8099
,因為這個Docker容器的8099
埠並沒有啟用,啟用的是Linux
這台機器上的8099
埠,所以需要通過IP
來指定。
整體思路明確了,接下來就開始動手操作。
編寫deploy腳本
前端
打開teprunner-frontend
文件夾,新建deploy/nginx.conf
文件:
/
路徑從user/share/nginx/html
讀文件,入口為index.html
,/api
轉發到//172.16.25.131:8099
。這個文件會拷貝到Docker鏡像中。新建Dockerfile
文件:
FROM
定義了基礎鏡像,可以理解為作業系統,前端項目基於nginx
來構建。WORKDIR
定義了鏡像當前工作目錄,意思是在執行後面COPY
操作時,鏡像目錄用哪一個。COPY
分別把dist
靜態文件和nginx.conf
配置文件拷貝到鏡像中,COPY
指令第一個參數是本機目錄,第二個參數是鏡像目錄。鏡像目錄通過WORKDIR
來指定,本機目錄通過Docker上下文來指定,新建build.sh
文件:
DockerContext
指定了Docker上下文為teprunner-frontend
根目錄。這裡的Shell腳本有兩個階段,第1階段是使用node
編譯:
docker run # 運行鏡像
--rm # 運行後刪除容器
-v $(pwd)/../:/data/src # $(pwd)指當前工作目錄,把根目錄掛載到data/src
-v /root/.npm/_logs:/root/.npm/_logs # 掛載日誌文件
-w /data/src/ # 鏡像當前工作目錄
$BUILDER_IMAGE # 運行鏡像為node:latest,用node編譯前端程式碼
/bin/sh -c "npm install && npm run build" # /bin/sh是shell可執行程式,調用執行npm命令
第2階段是打包成Docker鏡像:
docker build # 構建鏡像
-f $Dockerfile # 指定Dockerfile文件位置
-t $PkgName # 鏡像包名
$DockerContext # Docker上下文
後端
後端也是類似的,先新建deploy/Dockerfile
文件:
後端項目基於python:3.8
來構建,接著設置了時區,COPY . .
把Django源文件直接複製到了鏡像目錄/app/release
中,RUN
指令執行pip install
命令安裝依賴包,CMD
和RUN
有點區別,RUN
指令在docker build
時就執行,CMD
指令在docker run
時才執行,預定義啟動命令。
這裡簡化了遷移資料庫
migrate
等啟動命令,伺服器資料庫和本地用的同一個。
再新建build.sh
文件:
Python程式碼不需要編譯,打包成Docker鏡像就可以了。
部署到Ubuntu系統Docker
Linux系統是內核版本,它有很多發行版本,比如CentOS、Ubuntu,本文採用了Ubuntu,只有一個原因,它長的好看。
大學室友曾經衝動地把Windows系統換成了Ubuntu,還天天跟我們炫耀有多酷炫有多牛逼,過了兩三天發現Office不好用,也玩不了遊戲,就又換回來了。哈哈,Ubuntu平時玩玩就好了,除非是做Linux內核開發。
下載軟體:
- VMware 破解版
- Ubuntu Desktop 20.04
安裝過程此處不再另加贅述。打開虛擬機的Ubuntu:
打開Terminal,輸入su
,輸入密碼,切換到root
:
發現缺少許可權就
su
一下。
安裝curl
:
apt-get install curl
安裝docker
:
curl -fsSL //get.docker.com | bash -s docker --mirror Aliyun
使用ifconfig
查詢虛擬機IP:
不要選擇.git
和node_modules
文件夾,把teprunner-frontend
打成壓縮包。不要選擇.git
和__pycache__
文件夾,把teprunner-backend
打成壓縮包。複製前後端壓縮包到虛擬機Documents解壓:
Ubuntu Desktop的好處是提供了影像化操作介面,適合我這種小白用戶。使用命令行編輯工具vi
或者圖形編輯工具gedit
編輯teprunner-frontend/deploy/nginx.conf
文件中/api
轉發地址為你的虛擬機實際IP地址:
打開兩個Terminal,分別cd
到teprunner-frontend/deploy
和teprunner-backend/deploy
,執行./build.sh
命令。
如果執行提示
^M
之類報錯,那是因為在Windows編輯後複製到Linux格式不一致,使用apt-get install dos2unix
命令安裝工具後進行格式轉化,比如dos2unix build.sh
、dos2unix Dockerfile
。
前端構建截圖:
第一次因為要下載node依賴包和拉取nginx鏡像,會比較慢,第二次就快很多了。
後端構建截圖:
第一次因為要拉取python鏡像,會比較慢,第二次就快多了。
都構建完成後,輸入docker images
命令就能看到打包好的Docker鏡像了:
啟動前端鏡像:
docker run -p 80:80 teprunner-frontend
啟動後端鏡像:
docker run -p 8099:80 teprunner-backend
鏡像啟動後就變成了Docker容器,可以理解為一台虛擬主機。
-p
參數用於映射Ubuntu埠和Docker埠。可以添加-d
參數讓容器在後台運行。docker ps -a
查看容器,docker kill CONTAINER
或docker stop CONTAINER
退出容器。
最後可以在虛擬機中訪問http:127.0.0.1
進行登錄了,本地機器想要訪問的話,需要把127.0.0.1
改為你的虛擬機實際IP,比如//172.16.25.131
。
小結
本文先介紹了本地運行和Nginx部署的示意圖,涉及到跨域訪問和反向代理。接著編寫deploy腳本,編譯程式碼,構建鏡像。最後部署到Ubuntu系統的Docker中運行起來。在使用過程中,也感受到了Docker這一划時代技術的魅力,如果沒有Docker,我們需要在Ubuntu上面安裝nginx、node、python等軟體,有了Docker,我們只需要安裝Docker,其他都基於Docker鏡像構建就可以了。teprunner測試平台的用例採用的是程式碼形式,這就涉及到了程式碼存放位置的問題,為了讓pytest能調用執行,肯定是存放到文件裡面的。本文實踐給了個重要提醒,如果後端把程式碼直接寫入磁碟文件,每次打包鏡像部署後,就會把已保存的用例程式碼抹掉。解決這個問題的第一個辦法是用K8S,第二個辦法是把程式碼存資料庫。學習版採用了第二個辦法存資料庫,執行時動態從資料庫拿程式碼生成文件。第一個辦法思路借鑒:
最後,簡單聊下Docker和K8S,Docker是Docker公司的,K8S是Google的,Docker是家小公司搞的,在創建之初,並沒有考慮到「容器編排」這個功能,2014年 Google推出Kubernetes用於解決大規模場景下Docker容器編排的問題,2016年Kubernetes發布CRI統一介面,雖然Docker也在2016年發布了Docker Swarm,帶來了Docker在多主機多容器的編排解決方案,但是已經無法阻擋K8S取得這場容器編排戰爭的勝利。
參考資料:
//www.cnblogs.com/riwang/p/11883332.html