Docker部署實驗html
1、實驗背景java
最近對Docker很感興趣,對他的輕量化,便於擴展性非常癡迷,因此在工做之餘進行了一些探究,結合自身公司的運維場景,設計瞭如下實驗。web
說明:大多數場景都是使用的Java7或者Java8結合resin3或者resin4的Java中間件來跑服務的,因此在這裏我使用Java7和resin4來做爲實驗環境進行講解。爲了簡便演示,本應該編譯打包war包至webapps文件夾後啓動中間件,在這裏我只使用靜態頁來進行測試,實際環境把index.html換成ROOT.war便可。docker
2、Docker與虛擬化異同shell
不管是什麼技術交流活動,但凡講到Docker的主題與虛擬化的對比是必不可少的一個環節,因此儘管老生常談,我也在這裏囉嗦幾句。我儘管不是計算機學院的學生,可是在大學期間就對虛擬化很感興趣,回想一下那是我大三的時候,也就是12年左右,爲了作一個Esxi的實驗,從新買了一臺CPU支持虛擬化的筆記本,搭載了16G內存,在當年非常風光,dei誰跟誰說我是i7-16G內存,而後享受着同窗們羨慕的眼光,當年的主流本仍是2G內存呢,今後開啓了個人虛擬化實驗的探索。好像主題有些跑偏,那咱們言歸正傳。centos
先放一個老圖,從圖上能夠看出一個服務器的基本架構,從下往上是都由必不可少的硬件+操做系統組成。可是在第三層就有變化了,對於虛擬化來說,有一個Hypervisor層,而後之上的虛擬機都有一套完整的操做系統,並和宿主機互不影響,相互隔離。而對於容器來說,第三層不是Hypervisor,而是docker引擎,之上的docker容器沒有完整的操做系統,而是隻有一些庫文件,真正的內核仍是借用的宿主機的內核。bash
因此就會出現這樣一種狀況,在CentOS 7上運行了CentOS 6的Docker鏡像,在運行時會出現下圖的樣子:CentOS6的發行版卻擁有3.10的內核。服務器
其實簡而言之,虛擬化和容器只差了一層內核。若是理解到這個層次,那麼下面這個圖就不須要我再逐條分析了。架構
3、Docker落地實驗app
如今咱們還在用物理機上直接跑服務的方法,最大的問題就是測試說在本地測試後沒有問題,部署到線上就出問題,而後就是運維與開發的不斷扯皮。其實咱們也不想這樣,咱們也想合做愉快,可是總會出現這樣那樣的問題怎麼辦?那就使用如今比較流行的話題「不可變基礎設施+拒絕SSH」方法論(http://www.iteye.com/news/30970)。這個觀點是在2013年提出來的,在當時可能只是一個設想,不過在容器時代這個是一個最佳的實踐,由於容器默認就是不可ssh的,而且centos的docker鏡像自己竟然是沒有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-v0(commit標記)" 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端口查看了
4、自動化部署
好吧,這又是一個老生常談的主題,運維界一直致力的目標,因此我仍是來談一下如何自動部署,作到「持續部署」。
固然說到持續部署仍是離不開Jenkins,因此基本的思路就是在剛纔的命令上寫一些變量和shell腳本,咱們把部署思路分紅兩份,一個是編譯、打包、上線用的,另外一個是線上的服務器運行用的,因而創建兩個任務:DockerUpload和DockerDeploy,直接上腳本吧,你們做爲局內人一看就懂,再也不囉嗦。
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 root@192.168.254.134 "docker login --username=**@163.com --password=** registry.cn-*.aliyuncs.com"
ssh root@192.168.254.134 "docker pull registry.cn-*.aliyuncs.com/docker-yx/dictweb:${version}"
ssh root@192.168.254.134 "docker ps -q --filter "name=dict" |xargs docker stop"
ssh root@192.168.254.134 "docker run --rm --name dictweb-${version} -p 8081:8080 -dit registry.cn-*.aliyuncs.com/docker-yx/dictweb:${version} /bin/bash"
ssh root@192.168.254.134 "docker exec dictweb-${version} /usr/local/resin-4.0.55/bin/resin.sh start"
這樣在測試測完後就可使用DockerUpload任務把代碼打包成鏡像傳上去,而後運維人員使用DockerDeploy任務把對應版本的鏡像run起來。若是遇到問題直接寫對應版本號就能夠實現秒級回滾!
至此本篇文章已接近尾聲,可是你們確定還有疑問,剛纔不是說有日誌往哪裏打嗎?就目前環境來說日誌是打到容器裏的,可是這確定不是最佳方案,後面我會結合K8S和ELK等平臺講解日誌的處理問題,請你們持續關注個人博客。謝謝各位!
也歡迎高手從下方留言交流,或加qq 1848473726交流溝通。