1. 程式人生 > >一個小白的測試環境docker化之路

一個小白的測試環境docker化之路

ima services 重啟 image 說道 使用 搭建 大禮包 compress

本文來自網易雲社區

作者:葉子

學習docker搭建測試環境斷斷續續也有三個多月了,希望記錄一下這個過程。常言道,總結過去,展望未來嘛~文章淺顯,還望各位大神路過輕拍。

按照國際慣例,先說一下背景:

目前我所處的項目組不斷擴大和發展,因此質量保障維度也需要不斷擴展。然而多種質量保障維度的開展需要多套測試環境的支持,目前項目組裏只有一套測試環境,按照傳統方法一步步手工搭建測試環境費時費力,有什麽方法可以迅速搭建環境呢?當然是近幾年大火的docker啦。可是我是docker小白,之前只是簡單地看過幾篇docker入門的帖子,去官網上按照tutorial敲了一遍命令,但總感覺是紙上談兵,一到實戰環節,依然無從下手。

中國首富王健林說:“先定一個小目標“。我們的項目裏面除了java web應用就是java app應用,java web應用說白了就是tomcat麽,以前自己手動部署過,看上去不會太難,那就從這個開始,先用docker部署一個項目中的tomcat應用好了。docker方面的知識是零基礎,老大推薦了一本書叫《第一本docker書》。

技術分享圖片

這本書淺顯易懂,適合我這個小白,粗粗讀完前4章後,我就感覺自己可以上路了。

測試環境的應用模塊部署都是在ndp平臺上部署的,先簡單了解下ndp平臺部署web應用的原理,就是將代碼從git上拉下來,編譯打包好,找一臺雲主機,這臺雲主機上安裝了jdk和tomcat,然後把打包好的代碼放進tomcat裏,設置下端口號,啟動起來就好了。那如果用docker怎麽部署呢?讀完docker書就知道,其實一個docker容器就相當於一臺雲主機,我們的雲主機是linux系統,拉一個linux系統的鏡像,啟動這個鏡像的容器後,我在裏面裝個jdk和tomcat,這不就和我們的雲主機環境一模一樣了嘛~

到這裏思路就清晰多了,第一步先搞個和雲主機環境一樣的docker容器,網上搜了一下後,發現直接就有現成的tomcat鏡像,tomcat本身也依賴jdk,而且也是基於linux環境的,第一步立馬就做完了,這速度杠杠滴。那接下來就是拉取代碼,編譯打包,然後放進去啟動就可以了。於是乎,第一個問題就碰到了,代碼是有權限的,不是隨便就可以拉取的。回想以前在雲主機上拉取代碼,是在這臺雲主機上生成一對ssh密鑰,然後把公鑰上傳到git lab上,這樣就能獲得拉取代碼的權限了。都說實踐是檢驗真理的唯一標準,趕緊在剛剛啟動的docker容器裏試了一把,恩,行得通!可是這才一個docker容器啊,如果我再來幾個docker容器,每個容器都要生成一對ssh密鑰,然後上傳,豈不累死。 怎麽辦呢?馬克思主義哲學說道過,要透過現象看本質,git識別權限的本質是什麽?是在於私鑰和公鑰的匹配!公鑰在git服務器上,那我本地只要有對應的私鑰就可以了呀,我在創建容器的時候把一個git已有的公鑰所匹配的私鑰放進去,這樣容器就自帶git權限了嘛。

代碼拉下來以後,下一步就是編譯打包,那先研究下ndp平臺是怎麽部署我們測試環境的web應用的吧。看了一下,在ndp平臺上找到了這個web應用的一個build.xml,咦,這不就是ant工具的執行腳本麽,仔細一讀,果然是個編譯打包的腳本,其中關鍵的步驟是利用mvn clean install進行編譯打包的。ok,那在剛剛啟動的容器裏安裝一下ant和maven工具,然後用ant命令執行下這個build.xml,大功告成!

執行完ant命令以後,發現生成了一個compressed的文件夾,裏面主要是編譯打包後生成的東西,如下圖:

技術分享圖片 那麽這些編譯打包好的東西應該放在哪裏呢?再一次研究一下ndp部署的tomcat應用的目錄層級,心裏估摸著我把docker容器中的目錄層級弄得和ndp一樣應該不會有什麽問題。經過對比發現,compressed文件內容和測試環境tomcat應用的webroot文件內容是一樣的,吼吼~

技術分享圖片 此外,其他目錄層級不一樣的地方羅列了一下,大概有如下幾個:

技術分享圖片

大致讀了讀,tomcat是個腳本文件,用於啟動tomcat服務用的,裏面調用了./default/tomcat、init-functions和ratatelogs文件,那就把這些需要的文件都拷貝過來,並確保tomcat腳本裏所有的調用路徑都正確。

另外還需要修改的server.xml,將docBase地址指定為compressed的絕對路徑

技術分享圖片

將兩邊目錄層級弄的一模一樣後,就到了見證奇跡的時刻,運行啟動命令:

./tomcat start

查看日誌發現正常啟動,並無異常報錯,這真是個好兆頭。再用瀏覽器試試是否能訪問成功,看到預期的網頁打開了:)至此,第一個用docker方式部署的web應用模塊就完成啦

鑒於項目裏有多個不同的web模塊,它們所依賴的基礎環境都一樣,因此打算構建一個基礎鏡像,將所需要的相同的配置文件都放入基礎鏡像中,然後各自模塊的編譯打包過程寫成一個Dockerfile,這樣就不用在容器裏手敲命令進行編譯打包了,Dockerfile偽代碼如下:

FROM tomcat 基礎鏡像git clone 代碼COPY build.xml, 配置文件等到容器裏指定的路徑RUN build.xml,生成打包文件COPY 打包文件 TO destination filestart 啟動運行模塊

web應用搞定後,接下來就是java app模塊了。看了一下環境依賴,只需要裝個jdk環境就行,然後ndp上同樣有java app的構建腳本build.xml,再研究下npd部署的java app的目錄結構,該拷貝的拷貝,該修改的修改,照貓畫虎弄一遍,也啟動成功了。

接下來就是優化下tomcat和java app這兩個基礎鏡像,然後再寫寫各自模塊的Dockerfile就行了

技術分享圖片

每個模塊都有自己的Dockerfile,這樣就能迅速構建模塊鏡像並啟動部署了。至此,利用docker部署項目的應用模塊就完成了。

感謝上述過程中提供大力幫助的集美貌與才華於一身的婷婷同學~

--------------------

踩過的坑:

1、在執行build.xml腳本進行構建時,遇到類似如下的報錯:

技術分享圖片

原因是所需要的jar包因為在maven遠程倉庫中無法找到,首先檢查一下在docker容器安裝maven後,記得要把settings.xml設置成杭研的maven倉庫,如果還遇到這樣的錯誤,可能是杭研maven倉庫裏沒有該jar包,或者因為網絡等其他問題,無法下載該jar包。基本上通用的jar包都能下載成功,有一些基於模塊之間依賴的jar包無法下載到,如果你本地maven倉庫裏有這些jar包的話,可以拷貝進容器的maven倉庫裏,或者在容器裏拉取相互依賴模塊的代碼,通過mvm clean install命令將其打包進容器的maven倉庫裏。

2、在容器裏啟動應用後,遇到無法連通redis的問題:

技術分享圖片

代碼裏填寫的redis地址是雲主機的私有ip地址,容器所在的宿主機與redis在不同租戶下,因此無法通過私有ip進行連通訪問,容器的宿主機與redis同屬於一個機房,可通過機房ip進行訪問,與開發協商將代碼裏的依賴服務的ip地址都改為機房地址。

3、在docker容器裏拷貝git hub的私鑰後,執行git clone命令出現以下情況:

技術分享圖片

這個提示已經比較清楚了,.ssh/id_rsa 這個私鑰文件權限 too open,修改私鑰的權限:chmod 0600 id_rsa 後即可git clone代碼了。

--------------------

然而好景不長,很快我們就發現針對每個應用模塊寫Dockerfile這種方式的不足,一是構建的鏡像太多,每個模塊都要構建鏡像,然後啟動容器,鏡像也比較大,非常占空間;二是由於我們項目的特殊性,有些應用模塊在構建時需要依賴別的項目的jar,當時為了圖省事把依賴的jar直接放入基礎鏡像了,當依賴的jar發生變化時,我的基礎鏡像就要重新弄了,所有其他模塊的鏡像都要重新弄,這可要了命啊。看來此計不是長久之計,還需另謀出路。

經過之前的探索,我們知道,ndp的部署模式是一盞指路明燈,之前就是照著ndp的部署腳本照葫蘆畫瓢過來的,那ndp平臺是怎麽解決不同模塊之間的打包依賴問題呢?粗粗研究了一下,發現ndp是統一在一個地方打包,然後將打包好的compressed文件分發到別的雲主機上進行部署。那按照這個思路,我們也找一臺容器進行統一編譯打包,然後分發到不同的容器進行部署唄。

技術分享圖片

如此一來,我們只需要三個基礎鏡像,一個是用來編譯打包的鏡像,只需要安裝jdk,maven,ant等編譯打包工程所依賴的工具,一個是tomcat鏡像,一個是java環境鏡像,再寫一個腳本,偽代碼如下:

get compressed file  #對應模塊的打包文件get config file           #對應模塊的部署配置文件start module            #啟動運行模塊

如何獲取對應的打包文件呢? wget 命令可以從遠程服務器上下載文件,前提是不同容器之間的網絡需要互通。我們可以自己手動創建一個docker網絡,然後把不同的容器都手動加入這個網絡裏,這樣所有容器都在同一個網絡裏,應該就不存在網絡不通的問題了。獲取部署配置文件我們采用了git pull方式,在git上維護所有模塊的部署配置文件。

如此一來,當部署web模塊的時候就以tomcat鏡像來啟動容器並同時運行腳本,部署java app模塊的時候就以java app鏡像啟動容器並同時運行腳本,如此一來就不用給每個模塊寫Dockerfile制作鏡像了,也節省了不少構建鏡像的空間。

不過雖然節省了構建鏡像的空間,但容器運行的空間還是要提供的。一臺雲主機的基本配置是4核 CPU,8GB 內存,而項目的模塊多達20幾個,全部模塊放在一臺雲主機上可吃不消。肯定要搞多臺雲主機作為一個集群,把容器部署到這個集群中。這時候就要用到容器編排工具了,編排工具負責以下幾點:

  • 選擇最適合部署容器的機器,比如擁有最多空閑資源的機器

  • 發生機器故障,能自動把故障機器上的容器部署到其它節點。

  • 如果集群添加了新的機器,重新平衡容器的分配情況。

  • 如果容器故障了,重啟它。

  • ...

Docker本身內置了容器編排功能,稱為docker swarm mode。網上有很多關於docker swarm mode的資料,在此就不多闡述了,大致過程如下:

  1. 創建網橋:在每臺雲主機上創建docker_gwbridge網橋,註意,必須先創建網橋再創建swarm集群

  2. 創建集群:指定一臺雲主機作為manager,初始化swarm

  3. 加入集群:在其他雲主機上運行docker swarm join命令,使其加入該swarm集群

  4. 創建服務:使用docker service create來創建service,類似docker run 命令,創建的時候可直接運行腳本,執行部署過程

使用docker service create命令創建服務的時候需要指定大量參數,每次都要敲好長的命令,可以用docker compose yaml模板,類似如下:

version: "3.2"
services:
  compile:
    image: dockercloud/hello-world
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.hostname==docker-test
    ports:
      - "8080:8080"
    networks:
      - overlay_net

networks:
  overlay_net:
    driver: overlay

參考文章:《Docker Compose 配置文件詳解》

至此,我們解決了編譯打包過程中各個模塊相互依賴的問題,通過docker swarm mode方式實現了應用模塊集群化部署的方式,接下來的目標就是將這些應用模塊依賴的其他基礎服務拆分出來,如數據庫,redis,zookeeper等等,那樣子才算完整的一套獨立的測試環境。

網易雲容器服務為用戶提供了無服務器容器,讓企業能夠快速部署業務,輕松運維服務。

網易雲大禮包:https://www.163yun.com/gift

本文來自網易雲社區,經作者葉子授權發布。

相關文章:
【推薦】 6本互聯網技術暢銷書免費送(數據分析、深度學習、編程語言)!

一個小白的測試環境docker化之路