在前邊的安裝簡介中,我們提及到了基礎(chǔ)鏡像。在前面的部分我們已經(jīng)使用了Docker鏡像,舉例:ubuntu鏡像和training/webapp鏡像。
我們還發(fā)現(xiàn)Docker主機(jī)會從存儲中心下載鏡像。如果一個鏡像不存在,他就會自動從docker鏡像倉庫去下載:默認(rèn)的Docker Hub公共鏡像源。
在這一節(jié)中,我們將探討更多的關(guān)于docker鏡像的東西:
讓我們來列出本地主機(jī)上的鏡像。你可以使用docker images來完成這項任務(wù):
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
training/webapp latest fc77f57ad303 3 weeks ago 280.5 MB
ubuntu 13.10 5e019ab7bf6d 4 weeks ago 180 MB
ubuntu saucy 5e019ab7bf6d 4 weeks ago 180 MB
ubuntu 12.04 74fe38d11401 4 weeks ago 209.6 MB
ubuntu precise 74fe38d11401 4 weeks ago 209.6 MB
ubuntu 12.10 a7cf8ae4e998 4 weeks ago 171.3 MB
ubuntu quantal a7cf8ae4e998 4 weeks ago 171.3 MB
ubuntu 14.04 99ec81b80c55 4 weeks ago 266 MB
ubuntu latest 99ec81b80c55 4 weeks ago 266 MB
ubuntu trusty 99ec81b80c55 4 weeks ago 266 MB
ubuntu 13.04 316b678ddf48 4 weeks ago 169.4 MB
ubuntu raring 316b678ddf48 4 weeks ago 169.4 MB
ubuntu 10.04 3db9c44f4520 4 weeks ago 183 MB
ubuntu lucid 3db9c44f4520 4 weeks ago 183 MB
我們可以看到之前使用的鏡像。每次從Docker Hub下載一個鏡像就會在本地創(chuàng)建一個對應(yīng)的容器。
我們在鏡像列表中看到三個至關(guān)重要的東西。
ubuntu14.04鏡像源中可能有多種不同的鏡像。Ubuntu中我們會看到多個Ubuntu版本:10.04, 12.04, 12.10, 13.04, 13.10 and 14.04。每個容器有一個唯一的標(biāo)簽,讓我們來識別不同的鏡像,例如:
ubuntu:14.04
所以我們可以運行一個帶標(biāo)簽鏡像的容器:
$ sudo docker run -t -i ubuntu:14.04 /bin/bash
如果我們想要使用Ubuntu 12.04的鏡像來構(gòu)建,我們可以這樣做
$ sudo docker run -t -i ubuntu:12.04 /bin/bash
如果你不指定一個鏡像的版本標(biāo)簽,例如你只使用Ubuntu,Docker將默認(rèn)使用Ubuntu:latest鏡像。
提示:我們建議使用鏡像時指定一個標(biāo)簽,例如
ubuntu:12.04。這樣你知道你使用的是一個什么版本的鏡像。
現(xiàn)在如何獲取一個新的鏡像?當(dāng)我們在本地主機(jī)上使用一個不存在的鏡像時Docker就會自動下載這個鏡像。但是這需要一段時間下載這個鏡像。如果我們想預(yù)先加載這個鏡像,我們可以使用docker pull命令來下載它。像我們所說的我們下載centos鏡像。
$ sudo docker pull centos
Pulling repository centos
b7de3133ff98: Pulling dependent layers
5cc9e91966f7: Pulling fs layer
511136ea3c5a: Download complete
ef52fb1fe610: Download complete
. . .
我們看到每一層的鏡像都被下載下來了,現(xiàn)在我們可以直接使用這個鏡像,而不需要在下載這個鏡像了。
$ sudo docker run -t -i centos /bin/bash
bash-4.1#
Docker的特點之一是人們創(chuàng)建了各種各樣的docker鏡像。而且這些鏡像已經(jīng)被上傳到了Docker Hub。我們可以從Docker Hub網(wǎng)站來搜索鏡像。
http://wiki.jikexueyuan.com/project/docker/images/search.png" alt="" />
我們也可以使用docker search命令來搜索鏡像。譬如說我們的團(tuán)隊需要一個安裝了Ruby和Sinatra的鏡像來做我們的web應(yīng)用程序開發(fā)。我們可以通過docker search命令來搜索所有的sinatra鏡像來尋找我們合適的鏡像
$ sudo docker search sinatra
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
training/sinatra Sinatra training image 0 [OK]
marceldegraaf/sinatra Sinatra test app 0
mattwarren/docker-sinatra-demo 0 [OK]
luisbebop/docker-sinatra-hello-world 0 [OK]
bmorearty/handson-sinatra handson-ruby + Sinatra for Hands on with D... 0
subwiz/sinatra 0
bmorearty/sinatra 0
. . .
我們看到了返回了大量的sinatra鏡像。我們看到列表中有鏡像名稱、描述、Stars(衡量鏡像的流行程度-如果用戶喜歡這個鏡像他就會點擊stars)和官方自動構(gòu)建鏡像狀態(tài)。Stackbrew維護(hù)者官方倉庫源,鏡像源是自動構(gòu)建的,您可以驗證鏡像的來源和內(nèi)容。
我們回顧以前使用的鏡像,我們決定使用sinatra鏡像。到目前為止,我們已經(jīng)看到了兩種類型的鏡像,像ubuntu鏡像,我們稱它為基礎(chǔ)鏡像或者根鏡像。這些鏡像是由docker公司提供建立、驗證和支持。這些鏡像都可以通過自己的名字來標(biāo)示。
我們還可以看到用戶的鏡像,例如training/sinatra,并且我們可以使用docker pull命令來下載它。
$ sudo docker pull training/sinatra
現(xiàn)在我們的團(tuán)隊可以在自己的容器內(nèi)使用這個鏡像了。
$ sudo docker run -t -i training/sinatra /bin/bash
root@a8cb6ce02d85:/#
我們的團(tuán)隊發(fā)現(xiàn)training/sinatra鏡像雖然有用但是不是我們需要的,我們需要針對這個鏡像做出更改?,F(xiàn)在又兩種方法,我們可以更新和創(chuàng)建鏡像。
Dockerfile指令來創(chuàng)建一個鏡像。更新一個鏡像,首先我們要創(chuàng)建一個我們想更新的容器。
$ sudo docker run -t -i training/sinatra /bin/bash
root@0b2616b0e5a8:/#
注意:創(chuàng)建容器ID
0b2616b0e5a8,我們在后邊還需要使用它。
在我們的容器內(nèi)添加json
root@0b2616b0e5a8:/# gem install json
當(dāng)我們完成的時候,輸入exit命令來退出這個容器。
現(xiàn)在我們有一個根據(jù)我們需求做出改變的容器。我們可以使用docker commit來提交這個容器。
$ sudo docker commit -m="Added json gem" -a="Kate Smith" \
0b2616b0e5a8 ouruser/sinatra:v2
4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c
這里我們使用了docker commit命令。我們可以指定-m和-a標(biāo)示。-m標(biāo)示是允許我們指定提交的信息,就像你提交一個版本控制。-a標(biāo)示允許對我們的更新指定一個用戶。
我們也指定了我們想要創(chuàng)建的新鏡像來自(我們先前記錄的ID)0b2616b0e5a8和我們指定的目標(biāo)鏡像:
ouruser/sinatra:v2
讓我們分解這個步驟。我們先給這個鏡像分配了一個新用戶名字ouruser;接著,未修改鏡像名稱,保留了原鏡像名稱sinatra;最后為鏡像指定了標(biāo)簽v2。
我們可以使用docker images命令來查看我們的新鏡像ouruser/sinatra。
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
training/sinatra latest 5bc342fa0b91 10 hours ago 446.7 MB
ouruser/sinatra v2 3c59e02ddd1a 10 hours ago 446.7 MB
ouruser/sinatra latest 5db5f8471261 10 hours ago 446.7 MB
使用我們的新鏡像來創(chuàng)建一個容器:
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
root@78e82f680994:/#
Dockerfile創(chuàng)建鏡像使用docker commit命令能非常簡單的擴(kuò)展鏡像,但是它有點麻煩:在一個團(tuán)隊中不容易共享它的開發(fā)過程。為解決這個問題,我們可以使用一個新的命令來創(chuàng)建新的鏡像。
為此,我們創(chuàng)建一個Dockerfile,其中包含一組指令告訴docker如何創(chuàng)建我們的鏡像。
現(xiàn)在讓我們創(chuàng)建一個目錄,并且創(chuàng)建一個Dockerfile
$ mkdir sinatra
$ cd sinatra
$ touch Dockerfile
每一個指令鏡像就會創(chuàng)建一個新的層,讓我們看一個簡單的例子,我們的開發(fā)團(tuán)建創(chuàng)建一個自己的Sinatra鏡像:
# This is a comment
FROM ubuntu:14.04
MAINTAINER Kate Smith <ksmith@example.com>
RUN apt-get -qq update
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra
【注意】:
1)、每個指令前綴都必須大寫:
INSTRUCTION statement
2)、可以使用#注釋;
讓我們看看Dockerfile做了什么:
第一個指令FROM,告訴Docker使用哪個鏡像源,在這個案例中我們使用了一個Ubuntu 14.04基礎(chǔ)鏡像。
下一步,我們使用MAINTAINER指令指定誰是維護(hù)者。
最后,我們指定三個RUN指令,一個RUN指令在鏡像內(nèi)執(zhí)行命令。例如安裝包。這里我們在Sinatra中更新了APT緩存,安裝了Ruby和RubyGems。
注意:我們還提供了更多的Dockerfile指令參數(shù)。
現(xiàn)在我們使用docker build命令和Dockerfile命令來創(chuàng)建一個鏡像。
$ sudo docker build -t="ouruser/sinatra:v2" .
Uploading context 2.56 kB
Uploading context
Step 0 : FROM ubuntu:14.04
---> 99ec81b80c55
Step 1 : MAINTAINER Kate Smith <ksmith@example.com>
---> Running in 7c5664a8a0c1
---> 2fa8ca4e2a13
Removing intermediate container 7c5664a8a0c1
Step 2 : RUN apt-get -qq update
---> Running in b07cc3fb4256
---> 50d21070ec0c
Removing intermediate container b07cc3fb4256
Step 3 : RUN apt-get -qqy install ruby ruby-dev
---> Running in a5b038dd127e
Selecting previously unselected package libasan0:amd64.
(Reading database ... 11518 files and directories currently installed.)
Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...
. . .
Setting up ruby (1:1.9.3.4) ...
Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...
Processing triggers for libc-bin (2.19-0ubuntu6) ...
---> 2acb20f17878
Removing intermediate container a5b038dd127e
Step 4 : RUN gem install sinatra
---> Running in 5e9d0065c1f7
. . .
Successfully installed rack-protection-1.5.3
Successfully installed sinatra-1.4.5
4 gems installed
---> 324104cde6ad
Removing intermediate container 5e9d0065c1f7
Successfully built 324104cde6ad
我們使用docker build命令和-t來創(chuàng)建我們的新鏡像,用戶是ouruser、倉庫源名稱sinatra、標(biāo)簽是v2。
如果Dockerfile在我們當(dāng)前目錄下,我們可以使用.來指定Dockerfile
提示:你也可以指定
Dockerfile路徑
現(xiàn)在我們可以看到構(gòu)建過程。docker做的第一件事是通過你的上下文構(gòu)建。基本上是目錄的內(nèi)容構(gòu)建。docker會根據(jù)本地的內(nèi)容來在docker進(jìn)程中去構(gòu)建。
下一步,我們Dockerfile一步一步執(zhí)行命令。我們可以看到,每個步驟可以創(chuàng)建一個新的容器,在容器內(nèi)運行指令并且提交改變,就像我們早期看到的docker commit流程、當(dāng)所有的指令執(zhí)行完成之后,我們就會得到324104cde6ad鏡像(有助于標(biāo)記ouruser/sinatra:v2),然后所有中間容器會被刪除干凈。
我們可以從我們的新鏡像中創(chuàng)建一個容器:
$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash
root@8196968dac35:/#
注意:這是比較簡單的創(chuàng)建鏡像方法。我們跳過了你可以使用的一大堆指令。在后面的部門我們將會看到更多的指令指南,或者你可以參考
Dockerfile參考的例子和詳細(xì)描述每一個指令。
你可以給現(xiàn)有的鏡像添加標(biāo)記,然后提交和構(gòu)建。我們可以使用docke tag命令。讓我們給ouruser/sinatra鏡像添加一個新的標(biāo)簽。
$ sudo doc ker tag 5db5f8471261 ouruser/sinatra:devel
docker tag指令標(biāo)記鏡像ID,這里是5db5f8471261,設(shè)定我們的用戶名稱、鏡像源名稱和新的標(biāo)簽。
讓我們使用docker images命令查看新的標(biāo)簽。
$ sudo docker images ouruser/sinatra
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ouruser/sinatra latest 5db5f8471261 11 hours ago 446.7 MB
ouruser/sinatra devel 5db5f8471261 11 hours ago 446.7 MB
ouruser/sinatra v2 5db5f8471261 11 hours ago 446.7 MB
一旦你構(gòu)建或創(chuàng)造一個新的鏡像,你可以使用docker push命令推送到Docker Hub??梢詫ζ渌斯_進(jìn)行分享,或把它添加到你的私人倉庫中。
$ sudo docker push ouruser/sinatra
The push refers to a repository [ouruser/sinatra] (len: 1)
Sending image list
Pushing repository ouruser/sinatra (3 tags)
. . .
你也可以刪除你主機(jī)上的鏡像,某種程度上我們可以使用docker rmi命令。
讓我們刪除已經(jīng)不需要的容器:training/sinatra。
$ sudo docker rmi training/sinatra
Untagged: training/sinatra:latest
Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d
Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f
Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0
提示:在容器從主機(jī)中移除前,請確定容器沒有被使用。