前言
前一陣的工作,大多數(shù)是與部署相關(guān)的,通過將項(xiàng)目打包,然后利用docker,部署在AWS上去。就在這一段時(shí)間里面我便對(duì)docker產(chǎn)生了濃厚的興趣,這也就激發(fā)我去深入研究的一個(gè)動(dòng)力。那么下面開始我們的docker之旅。
什么是docker
我們可以首先通過以下網(wǎng)址對(duì)docker有一個(gè)認(rèn)識(shí):docker的講解。簡(jiǎn)單來說docker可以讓我們的部署變得更加簡(jiǎn)潔。(這里我就不做那么更詳細(xì)的解釋了,因?yàn)槲矣X得它總結(jié)的要比我總結(jié)好的多。)
為什么用docker
在沒出現(xiàn)docker的時(shí)候,我們完成的java web項(xiàng)目需要打成一個(gè)war。然后得在服務(wù)器中配置各種各樣的參數(shù),例如說jdk,tomcat,數(shù)據(jù)庫等。配置的周期相當(dāng)?shù)娜唠s并且繁瑣。但是現(xiàn)在有了docker,我們不但可以使用一個(gè)空的鏡像,從頭開始構(gòu)建,還可以使用之前各種大牛已經(jīng)build好的鏡像,直接使用。而且在項(xiàng)目需要遷移的時(shí)候,我們只需要在需要部署的地方,直接使用之前項(xiàng)目使用的docker放置好自己的項(xiàng)目即可,方便快捷。
docker的基本概念
docker最重要的三個(gè)概念是:鏡像(image),容器(container),倉庫(repository),在這三個(gè)概念中,鏡像是最重要的概念。
- 鏡像
我們可以把鏡像理解為一個(gè)文件系統(tǒng),并且是一個(gè)只讀的文件系統(tǒng)。鏡像是由一層層的只讀層構(gòu)造起來的,但是從使用者的角度來看我們只有一個(gè)鏡像而已。那么問題就來了,鏡像是只讀的,那么我們?cè)谑褂盟倪^程中,如果需要對(duì)它進(jìn)行修改,該怎么辦呢,別著急,這個(gè)就得看我們的容器了。 - 容器
容器是鏡像的一個(gè)運(yùn)行實(shí)例,可以不準(zhǔn)確的把鏡像當(dāng)作類,容器當(dāng)作對(duì)象。容器其實(shí)他的結(jié)構(gòu)是與鏡像相類似的,底部也是一層層的只讀層,只不過在最上層會(huì)存在一個(gè)存儲(chǔ)層,我們可以在這一層定制化我們的這個(gè)容器,還可以通過build命令,把容器打包成我們自己需要的鏡像。另外鏡像啟動(dòng)后會(huì)形成一個(gè)容器,容器在計(jì)算機(jī)中是一個(gè)進(jìn)程,但這個(gè)進(jìn)程對(duì)其他進(jìn)程并不可見。
容器的啟動(dòng)過程:
檢查鏡像是否在本地存在,如果不存在去遠(yuǎn)程倉庫下載
==>利用鏡像創(chuàng)建一個(gè)容器
==>啟動(dòng)剛剛創(chuàng)建的容器
==>分配一個(gè)文件系統(tǒng)給容器,并且在鏡像層外掛載一個(gè)可讀可寫層
==>從宿主主機(jī)的網(wǎng)橋接口中橋接一個(gè)給容器
==>從網(wǎng)橋中分一個(gè)ip地址給容器
==>執(zhí)行用戶指定的應(yīng)用程序
==>執(zhí)行完畢后容器自動(dòng)終止 - 倉庫
這個(gè)理解起來就很簡(jiǎn)單了,大家應(yīng)該有使用過git,他是有一個(gè)遠(yuǎn)程的倉庫,這個(gè)倉庫記錄著我們的代碼,和每一次我們提交的記錄。但是在這里,把docker的倉庫比做maven倉庫更加恰當(dāng),就相當(dāng)于我們可以去maven遠(yuǎn)程倉庫取我們需要的依賴,多個(gè)依賴構(gòu)成了我們的整個(gè)項(xiàng)目,這個(gè)思想同樣適用于docker。默認(rèn)情況下,我們都是從docker hub中取得的鏡像(http://registry.hub.docker.com/)
使用docker
實(shí)踐是檢驗(yàn)真理最好的方式,我會(huì)在不斷的實(shí)踐中給大家講解docker命令。
本人使用mac,所以所有操作都會(huì)在mac進(jìn)行。如果使用docker的話,強(qiáng)烈不推薦搭建使用windows系統(tǒng),因?yàn)閐ocker對(duì)于windows很不友好,用起來十分不方便,那怎么辦呢,win的同學(xué),可以在電腦上安裝虛擬機(jī),然后安裝一個(gè)linux系統(tǒng)(centos,red hat,ubantu)。
下面給出安裝的鏈接:
Mac:mac安裝docker的方法
Linux:centos安裝docker的方法
在使用docker之前,如果是不熟悉linux命令的,推薦強(qiáng)烈去學(xué)一下,因?yàn)槲易约焊杏X這對(duì)于docker的學(xué)習(xí)是很有幫助的。
安裝好docker,那就開始我們的表演。
1.docker search <鏡像名稱>
當(dāng)我們?cè)趯?duì)docker的鏡像一無所知的時(shí)候,我們可以通過查詢鏡像,看看自己想要的鏡像存不存在。例如說我們這里可以docker search tomcat。

2.docker pull <鏡像名稱>:<鏡像版本>
其實(shí)我們的版本都可以不用填寫,默認(rèn)情況下是latest,也就是去取最新的版本。

3.docker run -d -p <外部端口>:<內(nèi)部端口> <鏡像名稱>:<鏡像的tag>
打開terminal終端,在終端中輸入:docker run -d -p 8080:8080 tomcat 這里啟動(dòng)一個(gè)tomcat鏡像作為演示。熟悉tomcat的應(yīng)該知道,默認(rèn)的端口號(hào)為8080,所以我這里使用了默認(rèn)端口。這里解釋一下外部/內(nèi)部端口,這個(gè)很容易理解,docker在運(yùn)行的時(shí)候,會(huì)啟動(dòng)一個(gè)tomcat,這個(gè)tomcat的端口為8080。外部端口指的就是宿主電腦的端口。就是我們可以通過我們的電腦訪問的端口。
- -d <指的是后臺(tái)運(yùn)行容器>
- -p <指的是指定端口>
- --link <連接的容器名稱>:<連接的別名>
可以使容器和容器之間相互連接 - -v <掛載到容器的目錄>
- --volumes-from <可以掛載的數(shù)據(jù)卷容器名稱> (通過啟動(dòng)一個(gè)新容器,使用 -v 命令掛載一個(gè)目錄,然后通過這個(gè)命令把容器掛載到數(shù)據(jù)卷容器上,可以多個(gè)容器掛載同一個(gè)數(shù)據(jù)卷容器上,而且數(shù)據(jù)卷容器本身可以不是啟動(dòng)的狀態(tài)。)
-
-v <本地已有的目錄>(這個(gè)路徑必須是絕對(duì)路徑):<容器的目錄>。如下,我自己創(chuàng)建了一個(gè)宿主機(jī)與容器中的文件夾映射,然后創(chuàng)建了一個(gè)文件,宿主機(jī)相應(yīng)的也產(chǎn)生了文件。
docker run -v.png
local file.png
(Tips:其實(shí)我們本可以不使用pull進(jìn)行下載鏡像,因?yàn)閐ocker鏡像在啟動(dòng)的時(shí)候,如果放下這個(gè)鏡像不存在,那么自己會(huì)去下載鏡像。)如果想的話,可以添加上 -- name 作為這個(gè)啟動(dòng)容器的名稱,如果我們不定義名稱,可以通過容器的id操縱這個(gè)容器。并且docker run 是一個(gè)組合命令,實(shí)際上組合的是 create+start
docker run.png
4.docker create --name <容器名稱> <鏡像名稱>:<鏡像tag>
5.docker start <容器的id>
這里把create 以及start一起講一下,create命令就是在鏡像的只讀層的最上面加上一個(gè)存儲(chǔ)的可讀可寫層。上面的 -d 與 -p 的option 都是create命令的,創(chuàng)建一個(gè)容器可配的option相當(dāng)?shù)亩?,這里就不詳細(xì)說明了。create命令后,容器是處于stop狀態(tài)的,得需要start命令啟動(dòng)。start命令則是給容器分配一個(gè)進(jìn)程,然后啟動(dòng)起來。
6.docker images
查看本地已經(jīng)有的docker鏡像。
通過 docker images - -format [.ID]:[.Repository]指定顯示鏡像id以及名稱

7.docker rmi <容器名稱>:<容器tag>
移除已經(jīng)存在的指定的容器。

8.docker ps -a
查看所有的容器。
當(dāng)把-a換成-qa的時(shí)候就是查看所有容器的id。

9.docker exec -it <容器Id> /bin/bash
進(jìn)入docker 容器 docker exec -it(后面可以接上容器id或者容器名稱) /bin/bash
- -it 是 -i以及-t。
- -i是保持標(biāo)準(zhǔn)輸入打開
-
-t是表示分配一個(gè)偽終端。
docker exec.png
10.docker tag <已有鏡像名>:<已有鏡像版本> <新鏡像名>:<新鏡像版本>
我們可以使用docker tag tomcat:latest mytomcat:latest。這樣就會(huì)新生成一個(gè)鏡像名字叫做mytomcat,版本為latest,只有別名不同而已,但是同樣指向了同一個(gè)鏡像。
11.docker inspect <鏡像名稱>:<鏡像版本>
顯示鏡像的詳細(xì)信息,包括制作者,適應(yīng)框架,各層的數(shù)字摘要。
12.docker history <鏡像名稱>:<鏡像版本>
前面已經(jīng)說過,既然鏡像是一層一層構(gòu)成的,那么我們肯定可以看到,各層的記錄,使用此命令,可以看出鏡像發(fā)生的變化。過長(zhǎng)的信息會(huì)被自動(dòng)攔截我們可以使用 --no-trunc顯示信息完整的信息。
13.docker commit <進(jìn)程號(hào)>/<容器名稱> <鏡像名稱>:<版本號(hào)>
基于現(xiàn)有鏡像,形成自己的鏡像 。原理就是在原有的鏡像基礎(chǔ)上增加自己修改過的存儲(chǔ)層,疊加為一個(gè)新的鏡像,保存下來。成功后,會(huì)返回一個(gè) sha256的碼作為鏡像的唯一標(biāo)實(shí)。
形成新的自己的鏡像,一共有三個(gè)方法:
- 通過 commit 命令
- 通過模版進(jìn)行構(gòu)建
我們可以通過openVZ為我們提供的模板進(jìn)行創(chuàng)建,也可以通過自己導(dǎo)出的模板進(jìn)行創(chuàng)建,openvz網(wǎng)址 openvz模板下載地址。
我們以u(píng)bantu的模板為例。命令為cat ubuntu-x86_64-minimal.tar.gz | docker import ubuntu:14.04。執(zhí)行完以上命令,就可以通過docker images 看到我們的鏡像了。 - 通過Dockerfile文件進(jìn)行構(gòu)建。
但是docker commit 需要慎用,因?yàn)榫唧w做了什么修改任何人都是看到的,完全就是一個(gè)黑盒操作。而且進(jìn)行的刪除操作,并不是真正意義上的刪除,每一次的修改都是在上一次的基礎(chǔ)上,這使得 鏡像越來越臃腫。如果我們想要定制我們的docker鏡像可以使用dockerfile
13.docker save -o 導(dǎo)出的鏡像名稱(后綴為.tar) <鏡像名稱>:<鏡像的版本>
14.docker load --input 導(dǎo)出的鏡像名稱(后綴為.tar)
15.docker export -o 導(dǎo)出的鏡像名稱(后綴為.tar) <容器Id>
16.docker import 導(dǎo)出的鏡像名稱(后綴為.tar) <鏡像名稱>:<鏡像的版本>
前兩個(gè)命令是搭配在一起的,我們通過save命令,把鏡像打包成tar文件的形式,這就可以分享給別人進(jìn)行使用,然后其他人可以通過 load 命令將 導(dǎo)出的文件,保存到本地。
后兩個(gè)命令也是搭配起來的將正在運(yùn)行的容器,打包成一個(gè)tar文件。然后把tar文件import進(jìn)來,形成一個(gè)鏡像。
我們可以看出load和import命令十分相似,那他們的區(qū)別在哪呢?
- load 命令導(dǎo)入鏡像存儲(chǔ)文件到本地鏡像庫
-
import 導(dǎo)入一個(gè)容器快照到本地鏡像庫
容器快照文件將丟棄所有的歷史記錄以及元數(shù)據(jù)信息,僅保留快照時(shí)的狀態(tài)
鏡像存儲(chǔ)文件保持完整記錄,相對(duì)的體積也會(huì)更大。
在我動(dòng)手實(shí)踐的時(shí)候也明顯感覺到了,使用export要比save的速度快的多。
docker save load.png
這里的 load的時(shí)候犯了一個(gè)錯(cuò)誤,在后面跟上了鏡像的名稱與版本,其實(shí)是并不需要的,切記下次不會(huì)再加了。
docker import export.png
17.docker stop <容器的ID>
停止正在運(yùn)行的容器實(shí)例。
18.docker rm <容器的ID>
在刪除一個(gè)容器實(shí)例之前,應(yīng)該先要將容器停止。
主要支持的選項(xiàng):
- -f , --force = false 強(qiáng)制刪除一個(gè)正在運(yùn)行的容器
- -l , --link=false 刪除容器的連接,但是保存容器
- -v , --volumes=false 刪除容器掛載的數(shù)據(jù)卷
19.docker restart <容器的ID>
重新啟動(dòng)容器,將容器先停止,后啟動(dòng)。
20.docker build -t <生成鏡像的名稱>:<鏡像的版本> <Dockerfile的位置>
這是三種創(chuàng)建自己鏡像的方法之一,也是最好的一種方法,很多時(shí)候我們看到Dockerfile的位置上為".",表示的是當(dāng)前目錄,說明我們cmd和我們的Dockerfile在同一目錄下。
21.docker container prune
清理掉所有已經(jīng)停止的容器,在容器失敗停止后,做集體的清理特別方便。
后續(xù)
在下一篇文章,我會(huì)繼續(xù)整理有關(guān)Dockerfile的編寫,以及其他相關(guān)的內(nèi)容。我希望這樣的總結(jié),可以給大家?guī)韼椭矊?duì)自己梳理知識(shí)體系有所幫助,謝謝大家
本文參考書籍:《Docker技術(shù)入門與實(shí)戰(zhàn)》





