1. 程式人生 > >Docker部署實驗

Docker部署實驗

docker jenkins 容器

Docker部署實驗

一、實驗背景

最近對Docker很感興趣,對他的輕量化,便於擴展性很是癡迷,所以在工作之余進行了一些探究,結合自身公司的運維場景,設計了以下實驗。

說明:大多數場景都是使用的Java7或者Java8結合resin3或者resin4Java中間件來跑服務的,所以在這裏我使用Java7resin4來作為實驗環境進行講解。為了簡便演示,本應該編譯打包war包至webapps文件夾後啟動中間件,在這裏我只使用靜態頁來進行測試,實際環境把index.html換成ROOT.war即可。

二、Docker與虛擬化異同

無論是什麽技術交流活動,但凡講到Docker的主題與虛擬化的對比是必不可少的一個環節,所以盡管老生常談,我也在這裏啰嗦幾句。我盡管不是計算機學院的學生,但是在大學期間就對虛擬化很感興趣,回想一下那是我大三的時候,也就是

12年左右,為了做一個Esxi的實驗,重新買了一臺CPU支持虛擬化的筆記本,搭載了16G內存,在當年很是風光,dei誰跟誰說我是i7-16G內存,然後享受著同學們羨慕的眼光,當年的主流本還是2G內存呢,從此開啟了我的虛擬化實驗的探索。好像主題有些跑偏,那我們言歸正傳。

先放一個老圖,從圖上可以看出一個服務器的基本架構,從下往上是都由必不可少的硬件+操作系統組成。但是在第三層就有變化了,對於虛擬化來講,有一個Hypervisor層,然後之上的虛擬機都有一套完整的操作系統,並和宿主機互不影響,相互隔離。而對於容器來講,第三層不是Hypervisor,而是docker引擎,之上的docker容器沒有完整的操作系統,而是只有一些庫文件,真正的內核還是借用的宿主機的內核。

技術分享圖片

所以就會出現這樣一種情況,在CentOS 7上運行了CentOS 6Docker鏡像,在運行時會出現下圖的樣子:CentOS6的發行版卻擁有3.10的內核。

技術分享圖片

其實簡而言之,虛擬化和容器只差了一層內核。如果理解到這個層次,那麽下面這個圖就不需要我再逐條分析了。

技術分享圖片

三、Docker落地實驗

現在我們還在用物理機上直接跑服務的方法,最大的問題就是測試說在本地測試後沒有問題,部署到線上就出問題,然後就是運維與開發的不斷扯皮。其實我們也不想這樣,我們也想合作愉快,但是總會出現這樣那樣的問題怎麽辦?那就使用現在比較流行的話題“不可變基礎設施+拒絕SSH”方法論(http://www.iteye.com/news/30970)。這個觀點是在

2013年提出來的,在當時可能只是一個設想,不過在容器時代這個是一個最佳的實踐,因為容器默認就是不可ssh的,並且centosdocker鏡像本身居然是沒有vi命令的,只有cat,所以從官方設計的理念來講它就是不可被寫的(關於日誌的輸出後面再討論)。

說了這麽多估計大家都在等著實驗內容吧,好,那我們接下來來點幹貨,可以先喝口水潤潤嗓子。

1、配置阿裏雲鏡像倉庫

由於官方的docker hub在國內連接很慢,所以我首先在阿裏雲開通了容器鏡像服務。在點擊容器鏡像服務的時候不由分說先彈出一個輸入密碼框,這裏是一會會用到的docker hub登錄密碼,一定牢記。輸入完密碼後會跳轉到鏡像倉庫列表,但是是空的,所以需要創建鏡像倉庫,這時候會引導你創建“命名空間”,然後再創建倉庫,把所需信息填好就好了,最後一步選擇“本地倉庫”即可。

技術分享圖片


技術分享圖片


技術分享圖片

在本次實驗中創建的倉庫名稱是dictweb,創建完成後會告訴你使用方法,然後在左側鏡像加速器中還可以配置阿裏雲鏡像的加速地址。

技術分享圖片

等這一切先期工作都配置完成後,我們就可以開始自己創建初始鏡像了,也就是Java7+resin4

2、下載鏡像並初始化環境

我使用的基礎鏡像為Java7,然後把resin4的二進制包傳上去即可。

# docker pull Java:7 //拉取鏡像

# docker images //查看鏡像ID

REPOSITORY TAG IMAGE ID CREATE SIZE

java 7 5dc48a6b75af 5 months ago 584MB

# docker run --name dictweb-v0 -p 8081:8080 -itd 5dc48a6b75af /bin/bash

//運行容器命名為dictweb-v0,並將其放在後臺運行,映射宿主機端口號8081到容器的8080端口

# docker cp /tmp/resin-4.0.55.tar.gz dictweb-v0:/usr/local/ //resin的安裝包復制到容器裏的/usr/local/

# docker attach dictweb-v0 //進入容器shell界面

root@17507ed2e71f:/# cd /usr/local/

root@17507ed2e71f:/usr/local# tar xzvf resin-4.0.55.tar.gz //解壓

root@17507ed2e71f:/usr/local# cd resin-4.0.55

root@17507ed2e71f:/usr/local/resin-4.0.55# rm -rf webapps/ROOT/ //刪掉自帶文件,因為我們在做模板。

root@17507ed2e71f:/usr/local/resin-4.0.55# exit //退出容器

# docker login --username=****@163.com --password=***** registry.cn-**.aliyuncs.com

//登錄你的阿裏雲鏡像倉庫

# docker commit -a "author(作者名)" -m "dickweb-v0commit標記)" dictweb-v0(容器名) registry.cn-**.aliyuncs.com/docker-yx/dictweb:v0 //本地提交一次

# docker push registry.cn-**.aliyuncs.com/docker-yx/dictweb:v0 //提交到阿裏雲鏡像倉庫

至此,一版初始化的鏡像就創建完成了,下面就要用它進行持續部署業務了。

3、下載鏡像並進行第一版本的發布

假定我們現在已經編譯好了v1版本的war包,叫ROOT.war,但是為了演示簡便,就新建一個文件 /disk1/code/index.html 內容就是v1.0.0,所以我只需要輸入以下命令:

# docker pull registry.cn-hangzhou.aliyuncs.com/docker-yx/dictweb:v0 //拉取原始鏡像

# docker run --name dictweb-v1.0.0 -dit registry.cn-**.aliyuncs.com/docker-yx/dictweb:v0 /bin/bash //後臺啟動鏡像,命名為dictweb+版本號

# docker cp /disk1/code/index.html dictweb-v1.0.0:/usr/local/resin-4.0.55/webapps/ROOT //復制網頁文件至指定目錄

# docker stop dictweb-v1.0.0 //先停止鏡像

# docker commit -a "yx" -m "dickweb-v1.0.0" dictweb- v1.0.0 registry.cn-**.aliyuncs.com/docker-yx/dictweb:v1.0.0 //本地提交一下

# docker push registry.cn-**.aliyuncs.com/docker-yx/dictweb:v1.0.0 //提交至阿裏雲倉庫

# docker rm dictweb-v1.0.0 //刪除本地容器(可選,建議刪除,否則太多了)

至此第一個版本的鏡像已經提交到阿裏雲倉庫,接下來可以在目標服務器下載並運行了。

4、在目標服務器下載並啟動

註意!:不是在剛才的主機上操作的,是在另一些線上的服務器哦!

# docker login --username=***@163.com --password=** registry.cn-**.aliyuncs.com"

# docker pull registry.cn-**.aliyuncs.com/docker-yx/dictweb:v1.0.0 //拉取v1.0.0版本

# docker ps -q --filter "name=dict" |xargs docker stop //停掉上一個版本的容器

# docker run --rm --name dictweb- v1.0.0 -p 8081:8080 -dit registry.cn-**.aliyuncs.com/docker-yx/dictweb:v1.0.0 /bin/bash

//後臺啟動v1.0.0版本鏡像,並加上重命名、端口映射和停止後刪除的選項

# docker exec dictweb- v1.0.0 /usr/local/resin-4.0.55/bin/resin.sh start //啟動resin

啟動後就可以打開線上機器的8081端口查看了

技術分享圖片

四、自動化部署

好吧,這又是一個老生常談的主題,運維界一直致力的目標,所以我還是來談一下如何自動部署,做到“持續部署”。

當然說到持續部署還是離不開Jenkins,所以基本的思路就是在剛才的命令上寫一些變量和shell腳本,我們把部署思路分成兩份,一個是編譯、打包、上線用的,另一個是線上的服務器運行用的,於是建立兩個任務:DockerUploadDockerDeploy,直接上腳本吧,大家作為局內人一看就懂,不再啰嗦。

DockerUpload

#-------------------------------------------編譯--------------------------------------------------

docker pull registry.cn-**.aliyuncs.com/docker-yx/dictweb:v0

docker run --name dictweb-${version} -dit registry.cn-**.aliyuncs.com/docker-yx/dictweb:v0 /bin/bash

docker cp /disk1/code/index.html dictweb-${version}:/usr/local/resin-4.0.55/webapps/ROOT

#-------------------------------------------上傳--------------------------------------------------

docker stop dictweb-${version}

docker commit -a "yx" -m "dickweb-${version}" dictweb-${version} registry.cn-**.aliyuncs.com/docker-yx/dictweb:${version}

docker push registry.cn-**.aliyuncs.com/docker-yx/dictweb:${version}

docker rm dictweb-${version}

DockerDeploy

ssh [email protected] "docker login --username=**@163.com --password=** registry.cn-*.aliyuncs.com"

ssh [email protected] "docker pull registry.cn-*.aliyuncs.com/docker-yx/dictweb:${version}"

ssh [email protected] "docker ps -q --filter "name=dict" |xargs docker stop"

ssh [email protected] "docker run --rm --name dictweb-${version} -p 8081:8080 -dit registry.cn-*.aliyuncs.com/docker-yx/dictweb:${version} /bin/bash"

ssh [email protected] "docker exec dictweb-${version} /usr/local/resin-4.0.55/bin/resin.sh start"

這樣在測試測完後就可以使用DockerUpload任務把代碼打包成鏡像傳上去,然後運維人員使用DockerDeploy任務把對應版本的鏡像run起來。如果遇到問題直接寫對應版本號就可以實現秒級回滾!

技術分享圖片

至此本篇文章已接近尾聲,但是大家肯定還有疑問,剛才不是說有日誌往哪裏打嗎?就目前環境來講日誌是打到容器裏的,但是這肯定不是最佳方案,後面我會結合K8SELK等平臺講解日誌的處理問題,請大家持續關註我的博客。謝謝各位!

也歡迎高手從下方留言交流,或加qq 1848473726交流溝通。


Docker部署實驗