一個(gè)文件,兩行命令,帶你進(jìn)入研發(fā)效率快車道

摘要:本文不講晦澀難懂的概念、不講實(shí)現(xiàn)原理、不講內(nèi)核機(jī)制,僅僅從搭建一個(gè)簡(jiǎn)單web應(yīng)用的場(chǎng)景出發(fā),講講如何復(fù)用docker完成我們開發(fā)過程中的一些日常事務(wù),達(dá)到提升研發(fā)效率的目的。

Docker自12年發(fā)布,經(jīng)過幾年的蟄伏,15,16年勢(shì)頭猛勁,在大量的企業(yè)得到的實(shí)施,尤其是在互聯(lián)網(wǎng)、大數(shù)據(jù)相關(guān)領(lǐng)域更是勢(shì)不可擋。然而,在一些傳統(tǒng)行業(yè)、政府、事業(yè)機(jī)關(guān)、小企業(yè)中,Docker的使用率還是相對(duì)較低的,原因是多方面的,但其中很重要一個(gè)原因,源于對(duì)這些鋪天蓋地席卷而來的新技術(shù)的“恐懼”。企業(yè)發(fā)展到一定規(guī)模后,其技術(shù)架構(gòu)、組織架構(gòu)、研發(fā)模式基于已經(jīng)穩(wěn)定,新技采用勢(shì)必會(huì)對(duì)現(xiàn)有組織、業(yè)務(wù)產(chǎn)生影響,而這種影響的好壞,早期是很難判斷的,因此除了少數(shù)技術(shù)狂熱派,一般都會(huì)比較謹(jǐn)慎,然而小的初創(chuàng)公司,又很難承擔(dān)一次技術(shù)選型的失敗,因此更愿意去采用生態(tài)相對(duì)成熟、實(shí)施過程能有較大容錯(cuò)空間的技術(shù)。但是經(jīng)過這些年的市場(chǎng)的磨練,Docker其實(shí)已經(jīng)成為了云計(jì)算領(lǐng)域的一員老將,技術(shù)棧、生態(tài)各方面已經(jīng)得到完善。

本次以部署一個(gè)簡(jiǎn)單的web應(yīng)用為例,希望能給還徘徊在Docker門口的開發(fā)者、決策者們一些啟發(fā),如何利用Docker來簡(jiǎn)化日常研發(fā)工作、提升研發(fā)效率。

本文所講解示例如下圖,是一個(gè)簡(jiǎn)化的web應(yīng)用模型,包含了常用的組件,下面將詳細(xì)講解如何基于Docker快速完成整個(gè)環(huán)境的搭建和軟件的部署。

搭建MySQL數(shù)據(jù)庫(kù)

一行命令搞定!

docker run –dti-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

執(zhí)行docker ps|grep mysql命令,能看到mysql的容器已經(jīng)啟動(dòng),比起下載、安裝還有各種配置,夠快吧。

當(dāng)然這樣運(yùn)行起來的MySQL,還沒有辦法供外部服務(wù)直接訪問,,需要把容器內(nèi)的服務(wù)開個(gè)通道,讓外部服務(wù)通過宿主機(jī)的地址找到這個(gè)特殊通道,才能實(shí)現(xiàn)與外部服務(wù)的交互。

在宿主機(jī)上執(zhí)行netstat發(fā)現(xiàn)3306端口并未對(duì)外開放

把容器內(nèi)的服務(wù)映射到宿主機(jī)上

加上參數(shù) -p 宿主機(jī)監(jiān)聽port:容器開放port,建立“通道”,這樣當(dāng)用戶訪問宿主機(jī)的port時(shí),請(qǐng)求會(huì)自動(dòng)發(fā)送到容器內(nèi)對(duì)應(yīng)的端口上

docker run -dti -p 3306:3306 -eMYSQL_ROOT_PASSWORD=123456? --namemysql-service mysql:5.7

加上端口映射后就可以通過宿主機(jī)訪問了


對(duì)容器運(yùn)行時(shí)產(chǎn)生的數(shù)據(jù)進(jìn)行持久化

因?yàn)槊看螆?zhí)行docker run,相當(dāng)于從指定鏡像重新啟動(dòng)一臺(tái)電腦,鏡像是靜態(tài)不變的,那么意味著,重啟后之前運(yùn)行時(shí)產(chǎn)生的數(shù)據(jù)會(huì)全部丟失,一切回歸到初始狀態(tài),這個(gè)對(duì)數(shù)據(jù)庫(kù)是致命的,如果不能持久化存儲(chǔ)數(shù)據(jù),也就失去了其意義,Docker也就不可能走到現(xiàn)在。

在啟動(dòng)容器時(shí),加上參數(shù) -v 宿主機(jī)目錄:容器內(nèi)目錄,即可將宿主機(jī)的目錄mount到容器中,這樣容器銷毀時(shí),宿主機(jī)目錄的數(shù)據(jù)還在,重新啟動(dòng)容器,會(huì)繼續(xù)從宿主機(jī)加載數(shù)據(jù),借尸還魂,很機(jī)智。

docker run -dti -p 3306:3306 -eMYSQL_ROOT_PASSWORD=123456 -v /usr1/mysql_data:/var/lib/mysql? --name mysql-service mysql:5.7

現(xiàn)在運(yùn)行起來的MySQL就基本上已經(jīng)能滿足日常的需求了。

當(dāng)然,MySQL鏡像本身還提供了強(qiáng)大的業(yè)務(wù)參數(shù)(這個(gè)是鏡像制作者提供的,并非Docker提供),通過dockerrun的 -e 參數(shù)指定容器運(yùn)行的環(huán)境變量(等價(jià)于Dockerfile里的ENV參數(shù)),實(shí)現(xiàn)相應(yīng)的mysql能力,非常有用:

MYSQL_ROOT_PASSWORD:指定root用戶的密碼

MYSQL_USER: 新創(chuàng)建一個(gè)普通用戶

MYSQL_PASSWORD:新創(chuàng)建用戶的密碼

MYSQL_DATABASE:新創(chuàng)建一個(gè)database

MYSQL_ALLOW_EMPTY_PASSWORD:是允許無密碼登陸

想要使用時(shí)只需要通過加到命令行里即可,如:

docker run -d -p 3306:3306 --namemysql-service -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_USER=visitor -eMYSQL_PASSWORD=visitor -e MYSQL_DATABASE=visitordb -eMYSQL_ALLOW_EMPTY_PASSWORD=true -v /usr1/mysql_data:/var/lib/mysql? mysql:5.7

這為我們制作業(yè)務(wù)鏡像提供了一些參考,把部署、運(yùn)行時(shí)所需要的變量,通過容器環(huán)境變量的方式傳遞給業(yè)務(wù)組件,當(dāng)然業(yè)務(wù)組件也需要實(shí)現(xiàn)從這些約定好的變量里取值。

使用定制的MySQL鏡像,初始化數(shù)據(jù)

當(dāng)然,僅僅把MySQL啟動(dòng)起來大部分場(chǎng)景下是不夠的,還需要?jiǎng)?chuàng)建業(yè)務(wù)需要的database、tables,有些時(shí)候可能還要導(dǎo)入一些初始的數(shù)據(jù)。

接下來就講一下,如何通過對(duì)官方鏡像進(jìn)行定制,實(shí)現(xiàn)在啟動(dòng)容器時(shí),自動(dòng)執(zhí)行指定腳本,來創(chuàng)建表、初始化數(shù)據(jù)。

定制鏡像,就是基于官方的mysql鏡像,加上一些腳本、修改一些權(quán)限,再統(tǒng)一打包到新的鏡像里,在容器啟動(dòng)后自動(dòng)執(zhí)行這些腳本,做一些我們需要的業(yè)務(wù)操作。

首先,我們以mysql:5.7作為基礎(chǔ)鏡像

FROM mysql:5.7(語法:FROM 鏡像名稱:鏡像版本號(hào))

然后,把需要在MySQL容器啟動(dòng)后執(zhí)行的腳本拷貝到目錄/docker-entrypoint-initdb.d下。(MySQL鏡像啟動(dòng)后會(huì)掃描這個(gè)目錄,然后自動(dòng)執(zhí)行里面的shell和sql腳本)

COPY ./setup.sh

/docker-entrypoint-initdb.d/setup.sh? (語法:COPY 文件所在的主機(jī)路徑:鏡像中的絕對(duì)路徑)

接著,把setup.sh會(huì)引用到的其它文件,如shell,sql,config等,放到腳本中引用的目錄下。(如果有多個(gè)腳本需要執(zhí)行,都放在mysql指定目錄下時(shí),mysql并不知道腳本的執(zhí)行先后順序,因此一般是在mysql指定目錄下放一個(gè)執(zhí)行入口文件,在該文件中去按業(yè)務(wù)邏輯調(diào)用其它文件)

COPY ./init.sql /myinfo/init.sql

最后,在執(zhí)行shell腳本時(shí),希望root用戶不輸入密碼就能登陸MySQL,這里需要按MySQL鏡像的規(guī)范,設(shè)置一個(gè)環(huán)境變量:

ENV MYSQL_ALLOW_EMPTY_PASSWORD yes(語法:ENV 環(huán)境變量名稱 環(huán)境變量值)

這樣就生成了我們需要的Dockerfile文件

執(zhí)行 docker build . -t mysql:cust1

就能生成我們自己的鏡像了,后面加上參數(shù)-t就可以給生成的鏡像打上標(biāo)簽,以便進(jìn)行版本管理。運(yùn)行該鏡像的命令與最開始提到的一樣,只是鏡像的版本需要使用最新生成的mysql:cust1,這里不再贅述。

上面MySQL的示例,涵蓋了80%常用的docker制作和運(yùn)行的指令和參數(shù),這也就是我一直認(rèn)為,Docker技術(shù)也許很高深,但使用確實(shí)很簡(jiǎn)單的原因。

搭建tomcat,運(yùn)行后臺(tái)服務(wù)

接下來按照制作MySQL鏡像的方式,制作tomcat服務(wù)鏡像,一個(gè)帶有VisitorService應(yīng)用的tomcat定制鏡像,這里不再一步步講解,直接把成品的Dockerfile拿出來給大家分享。

FROM tomcat:7-jre8

COPY ./VisitorService.war /usr/local/tomcat/webapps

就是這么簡(jiǎn)單,兩行搞定,思路和寫MySQL的Dockerfile是一樣的:

1、先選擇一個(gè)基礎(chǔ)鏡像:因?yàn)槌绦蚴腔贘DK1.8開發(fā)的,所以選擇了tomcat:7的jre1.8版本進(jìn)行定制,具體還有哪些可用的鏡像版本,可以在dockerhub官網(wǎng)查到

2、然后把自定義的內(nèi)容塞到鏡像里:把編譯好的war包拷貝到tomcat的webapps目錄下,就像平時(shí)在自己測(cè)試機(jī)上操作一樣。如果我們不想每次編譯完war包都重新構(gòu)建鏡像,也可以用類似于MySQL目錄映射的方法,在運(yùn)行tomcat鏡像時(shí),把本地存放war包的路徑,映射到容器的webapps目錄下。

3、設(shè)置環(huán)境變量:因?yàn)閼?yīng)用中會(huì)連接數(shù)據(jù)庫(kù),需要在啟動(dòng)容器時(shí),把數(shù)據(jù)庫(kù)信息加入到環(huán)境變量中,或在dockerfile中通過EVN參數(shù)設(shè)置,但因?yàn)橹凳菚?huì)變的,直接寫在dockerfile中,靈活性會(huì)差很多,因此我們采用了在啟動(dòng)時(shí)通過-e 的方式來設(shè)置,代碼里已實(shí)現(xiàn)從環(huán)境變量獲取這些信息。

最終運(yùn)行業(yè)務(wù)軟件鏡像容器的命令參考如下,命令行完成了目錄映射、環(huán)境變量設(shè)置,并指定要啟動(dòng)的鏡像版本:

docker run -p 9999:8080 -v 本地目錄/war文件:/usr/local/tomcat/webapps/xxx.war-eMYSQL_ADDR=mysql_ip:3306 -e MYSQL_DB=visitordb -e MYSQL_USER=visitor -eMYSQL_PWD=visitor -dti tomcat:7-jre8

搭建nginx,運(yùn)行靜態(tài)web服務(wù)

與Tomcat類似,也是有兩種方法

一種是,把需要部署在Nginx上的文件,以及配置打包到鏡像中:

FROM nginx:v2

COPY ./index.html /usr/visitor/index.html

COPY ./visitor.conf/etc/nginx/conf.d/visitor.conf

另一種是,從本地目錄映射:

docker run -p 80:80 -v 本地目錄/xx.conf:/etc/nginx/conf.d/xx.conf -v本地目錄:容器目錄-dti nginx

搭建并運(yùn)行Redis服務(wù)

因?yàn)橹皇谴嫒∫恍┚彺鏀?shù)據(jù),因此不考慮對(duì)容器內(nèi)的數(shù)據(jù)做持久化,直接放在容器里,因此這里不對(duì)redis鏡像做任何改造,直接使用。

docker run –p 6379:6379 –dti redis:2.8.23

大功告成

好了,一套簡(jiǎn)易的web應(yīng)用環(huán)境就搭好了,下面就是最終效果

我們來對(duì)比一下Docker幫我們提升了多少效率:


環(huán)境搭建效率提升明顯

說實(shí)話,以前搭環(huán)境最怕的就是像Nginx這種,下完還要編譯之后才能運(yùn)行的,一旦報(bào)錯(cuò),那真是對(duì)耐性的考驗(yàn)?,F(xiàn)在好了,一個(gè)Dockerfile,加docker build,docker run兩個(gè)命令,輕輕松松搞定環(huán)境的搭建,以前這些困難全沒了。

最關(guān)鍵的是,日常研發(fā)過程中,搭建3至5套環(huán)境是最基本的要求了,使用編寫好的Dockerfile,可以讓我們快速完成各種TEST/QA/STAGE環(huán)境、Demo演示環(huán)境的搭建與復(fù)制,而不需要為拷貝動(dòng)輒幾十G的安裝包而苦惱,也不會(huì)因?yàn)楦鞲鳝h(huán)境操作系統(tǒng)版本的差異而痛苦,著實(shí)為我們省了不少時(shí)間和精力。

后記

正因?yàn)镈ocker這么火,所有的公有云廠商不約而同的都提供了容器服務(wù),這進(jìn)一步降低了用戶的使用門檻,讓企業(yè)用戶無需關(guān)心日常運(yùn)維、問題處理、版本升級(jí)、技術(shù)演進(jìn)等紛繁復(fù)雜的事務(wù),使用戶更專注于自身業(yè)務(wù)競(jìng)爭(zhēng)力的提升。

華為云提供的容器服務(wù)包括云容器引擎服務(wù)(CCE)和云容器實(shí)例服務(wù)(CCI),圍繞著云容器,還提供了鏡像管理、應(yīng)用編排、應(yīng)用運(yùn)維管理、微服務(wù)管理、云中間件等一系列構(gòu)建容器化應(yīng)用生態(tài)所需的配套服務(wù),并在兼容社區(qū)的基礎(chǔ)上,針對(duì)游戲、電商、基因等行業(yè),對(duì)容器的網(wǎng)絡(luò)性能、計(jì)算性能、存儲(chǔ)性能、安全等方面進(jìn)行了優(yōu)化,能滿足廣大用戶CI/CD、自動(dòng)化運(yùn)維、秒級(jí)彈性伸縮、高并發(fā)低時(shí)延、高性能運(yùn)算的訴求。

趕緊點(diǎn)擊下面的鏈接來體驗(yàn)一下吧:

華為云容器引擎:https://console.huaweicloud.com/cce2.0/

華為云容器實(shí)例:https://console.huaweicloud.com/cci/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容