這組概念不多會讓人產生疑惑,可是這二者的區別很是重要。Docker在鏡像(image)中運行你的代碼,而不是Dockerfile。Dockerfile是經過docker build命令來編譯鏡像的配置文件。python
若是你去瀏覽一下public index的話,你將會看到那裏羅列了不少鏡像文件。可是,也許有些奇怪的是,你將看不到任何編譯出它們的dockerfile。鏡像文件就是從Dockerfile編譯而獲得的不透明資產(opaque asset )。linux
當你用docker push命令發佈本身的鏡像的時候,你發佈的不是任何你的代碼,而是由你的代碼編譯出來的鏡像文件。web
註冊表(鏡像註冊表,registry)和索引(鏡像索引,index)這兩個概念,以及它們的區別也很特殊。docker
一個索引(index)用來管理用戶帳號,權限,搜索,打標籤(tagging),以及其它能夠方便的經過Web界面來完成的工做。json
一個註冊表(registry)則是真正的用來保存、提供鏡像文件的概念。它經過索引(index)來完成用戶認證步驟。ubuntu
當你執行docker search命令的時候,Docker會到index裏執行查找工做,而不是registry。從實際上來講,Docker會在索引(index)所知道的多個註冊表(registry)中進行查找。api
而當你執行docker push 或者 docker pull操做的時候,index會判斷你是否有權限訪問或者修改該鏡像文件,若是經過index的認證操做的話,registry則進行實際的鏡像存儲工做或者將鏡像文件發送給請求端。一樣,index會知道你想訪問的鏡像的存儲位置(哪一個registry上),而後將訪問請求轉向到相應的registry。安全
另外,當你在本地環境下,執行相似docker images工做的時候,你所打交道的既不是一個index,也不是一個registry,而是二者都會有一點。bash
Docker 使用相似於Github或者其餘SCM工具的倉庫概念。固然,它們也不徹底等價。
下面這三個問題值得咱們先好好思考一下:服務器
實際上,這是一個問題,由於鏡像倉庫是全部這些概念的合集,而不是單獨的任何一個。 此外,當你執行docker images的話你將獲得相似以下的輸出:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
上面鏡像列表的東西看起來像一個倉庫列表?嗯?實際上,那些GUID纔是Docker鏡像,但你並不和他們進行交互。
讓咱們來仔細看看這個問題。
當你執行docker build或者docker commit的時候,你能夠給它指定一個鏡像名稱。這個名稱通常來講都是相似username/image_name這樣的格式,但這不是必須的。實際上你能夠給鏡像名稱指定任何字符,甚至是那些已經公開的衆所周知鏡像的名稱。
可是,等你進行docker push的時候,index將會檢查鏡像的名字,查看是否有和其匹配的倉庫(respsitory)。若是找到了匹配的倉庫,將會繼續檢查你是否有權限操做這個倉庫。若是你有權限的話,那麼一個新版本的鏡像將成功的存儲(發佈)到這個倉庫中。從中咱們能夠看出,registry會保持一個倉庫列表,每一個倉庫都有本身的名字。而每一個倉庫都保存的都是經過GUID來標識的鏡像文件列表。
這裏又出現了標籤的概念。你能夠對任何一個鏡像進行打標籤操做,而且在同一個倉庫中,爲同一個鏡像保存不一樣的版本,不一樣的版本經過GUID來進行區分。咱們能夠經過username/image_name:tag這種方式來經過標籤訪問不一樣版本的鏡像。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
咱們再來從新看一下docker images的輸出結果,應該會有新的認識吧。咱們有5個不一樣版本的ubuntu的鏡像,這些鏡像經過標籤來區分。鏡像倉庫經過ubuntu這個名字來管理全部這些鏡像。也許你會認爲ubuntu是一個鏡像的名字,但實際上這是一個倉庫的名字,它告訴咱們它從哪裏取得,或者在發佈鏡像的時候將保存到何處。
此外,倉庫名稱還有它特殊的命名模式(schema),索引(index)會將倉庫名字的第一部分解析爲用戶名,而且將定位倉庫的位置。
那麼問題就出現了,假設咱們有一個Docker鏡像 thoward/scooby_snacks。
這個鏡像的「正式的名字」應該是thoward/scooby_snacks,儘管實際上咱們潛意識裏會認爲它的名字就是scooby_snacks (這有點相似Github等服務裏的倉庫的概念)
實際上,當Docker的文檔裏說道倉庫的時候,有時候指的是包含用戶名在內的全部東西,而有時則只是去掉用戶名後的部分。
這是由於一些倉庫(好比ubuntu)等沒有用戶名。對用戶名作特殊處理很是重要,由於index會用它來作認證操做,因此倉庫名字裏的用戶名部分有它本身獨特的意思。
到這裏咱們已經對Docker複雜的遠程存儲體系作出了說明,以及這裏面容易讓人混淆的幾個概念。可是,docker images命令顯示的內容都是本機上存在的資源。
那麼本地資源都保存在什麼位置呢?咱們首先來看看 /var/lib/docker/這個文件夾下的內容。
打開這個文件夾下的 repositories 文件,你將會看到相似下面這樣的JSON 文件:
$ sudo cat /var/lib/docker/repositories | python -mjson.tool
{
「Repositories」: {
「ubuntu」: {
「12.04″: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「12.10″: 「b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc」,
「latest」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「precise」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「quantal」: 「b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc」
}
}
}
看看,是否是正好和docker images的內容一致呢。
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
接着,咱們再來看看 /var/lib/docker/graph/這個文件夾:
$ sudo ls -al /var/lib/docker/graph
total 24
drwx—— 6 root root 4096 Nov 22 06:52 .
drwx—— 5 root root 4096 Dec 13 04:25 ..
drwxr-xr-x 3 root root 4096 Dec 13 04:26 27cf784147099545
drwxr-xr-x 3 root root 4096 Nov 22 06:52 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c
drwxr-xr-x 3 root root 4096 Nov 22 06:52 b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc
drwx—— 3 root root 4096 Nov 22 06:52 _tmp
這些輸出結果可能有點晦澀(Not terribly friendly),可是從中咱們能夠看出Docker是使用repositories JSON文件來記述鏡像信息的,此JSON文件包含了倉庫名、標籤、以及標籤對應的鏡像ID。
咱們有兩個來自ubuntu倉庫的鏡像,這其中標籤爲12.04,precise和latest都指向的是同一個鏡像,其ID爲 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c (這個ID長度爲64位,可是咱們可使用其12位的簡短模式,好比8dbd9e392a96)。
那麼這些以鏡像ID命名的文件夾下面又保存了什麼東西呢?
$ sudo ls -al /var/lib/docker/graph/8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c
total 20
drwxr-xr-x 3 root root 4096 Nov 22 06:52 .
drwx—— 6 root root 4096 Nov 22 06:52 ..
-rw——- 1 root root 437 Nov 22 06:51 json
drwxr-xr-x 22 root root 4096 Apr 11 2013 layer
-rw——- 1 root root 9 Nov 22 06:52 layersize
這個文件夾下的內容以下:
$ sudo cat /var/lib/docker/graph/8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c/json | python -mjson.tool
{
「comment」: 「Imported from -「,
「container_config」: {
「AttachStderr」: false,
「AttachStdin」: false,
「AttachStdout」: false,
「Cmd」: null,
「Env」: null,
「Hostname」: 「」,
「Image」: 「」,
「Memory」: 0,
「MemorySwap」: 0,
「OpenStdin」: false,
「PortSpecs」: null,
「StdinOnce」: false,
「Tty」: false,
「User」: 「」
},
「created」: 「2013-04-11T14:13:15.57812-07:00″,
「docker_version」: 「0.1.4″,
「id」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」
}$ sudo cat /var/lib/docker/graph/8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c/layersize
131301903$ sudo ls -al /var/lib/docker/graph/8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c/layer
total 88
drwxr-xr-x 22 root root 4096 Apr 11 2013 .
drwxr-xr-x 3 root root 4096 Nov 22 06:52 ..
drwxr-xr-x 2 root root 4096 Apr 11 2013 bin
drwxr-xr-x 2 root root 4096 Apr 19 2012 boot
drwxr-xr-x 4 root root 4096 Nov 22 06:51 dev
drwxr-xr-x 41 root root 4096 Nov 22 06:51 etc
drwxr-xr-x 2 root root 4096 Apr 19 2012 home
drwxr-xr-x 11 root root 4096 Nov 22 06:51 lib
drwxr-xr-x 2 root root 4096 Nov 22 06:51 lib64
drwxr-xr-x 2 root root 4096 Apr 11 2013 media
drwxr-xr-x 2 root root 4096 Apr 19 2012 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2013 opt
drwxr-xr-x 2 root root 4096 Apr 19 2012 proc
drwx—— 2 root root 4096 Nov 22 06:51 root
drwxr-xr-x 4 root root 4096 Nov 22 06:51 run
drwxr-xr-x 2 root root 4096 Nov 22 06:51 sbin
drwxr-xr-x 2 root root 4096 Mar 5 2012 selinux
drwxr-xr-x 2 root root 4096 Apr 11 2013 srv
drwxr-xr-x 2 root root 4096 Apr 14 2012 sys
drwxrwxrwt 2 root root 4096 Apr 11 2013 tmp
drwxr-xr-x 10 root root 4096 Nov 22 06:51 usr
drwxr-xr-x 11 root root 4096 Nov 22 06:51 var
看到這裏你應該有些頓悟了吧,這就是咱們爲何即便咱們不和遠程索引或者註冊表交互也能經過倉庫名來使用一個鏡像的原理了。由於一旦你講鏡像從遠程下載到本地,Docker能夠經過倉庫名稱來使用它們。當你建立本身的Dockerfile的時候也不例外。
首先咱們來看一個最簡單的例子。建立以下的Dockerfile:
FROM ubuntu
這個配置文件除了引入ubuntu這個鏡像做爲基礎層(base layer)以外,幾乎什麼都沒幹。不過這樣也足以保證他能正常工做了。
接着,咱們來運行 docker build -t scooby_snacks 命令。這個命令將會在咱們指定的位置(例子裏是當前文件夾,即」.」)尋找Dockerfile文件,並基於此進行鏡像編譯。這裏的 scooby_snacks 是倉庫的名字。
$ docker build -t scooby_snacks .
Uploading context 64184320 bytes
Step 1 : FROM ubuntu
—> 8dbd9e392a96
Successfully built 8dbd9e392a96
怎麼樣,標準輸出立顯示了出現了「Uploading context」的字眼,這是把此鏡像發佈到官網上的意思麼?
讓咱們來檢查一下就知道了:
$ docker search scooby_snacks
NAME DESCRIPTION STARS OFFICIAL TRUSTED
看來上面咱們建立的鏡像尚未被公開發布。
那上面那句話是什麼意思呢?
我也不知道,可是咱們能夠忽略它。也許它是將鏡像文件保存到本機的意思吧。
$ sudo cat /var/lib/docker/repositories | python -mjson.tool
{
「Repositories」: {
「scooby_snacks」: {
「latest」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」
},
「ubuntu」: {
「12.04″: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「12.10″: 「b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc」,
「latest」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「precise」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「quantal」: 「b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc」
}
}
}
從上面的結果來看,Docker只是將它「uploaded」到了/var/lib/docker。
一樣,咱們也能夠經過docker images命令來確認這一結果:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
scooby_snacks latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
這就是咱們構建鏡像文件的結果。Docker很聰明,因爲咱們是基於ubuntu:latest這個鏡像來建立的scooby_snacks,並且沒有作任何定製修改,因此它的鏡像ID也是8dbd9e392a96。
下面,咱們來試着對基礎層作一些修改,而後編譯出一個新的層(layer)來。
咱們經過修改 Dockerfile 文件增長以下內容來實現:
FROM ubuntu
RUN touch scooby_snacks.txt
編輯完以後,咱們再次運行「docker build -t scooby_snacks .」來構建這個鏡像。
$ docker build -t scooby_snacks .
Uploading context 64184320 bytes
Step 1 : FROM ubuntu
—> 8dbd9e392a96
Step 2 : RUN touch scooby_snacks.txt
—> Running in 86664242766c
—> 91acef3a5936
Successfully built 91acef3a5936
新的構建完成以後,會在/var/lib/docker/graph下面一個新的文件夾
$ sudo ls -al /var/lib/docker/graph
total 28
drwx—— 7 root root 4096 Dec 13 06:27 .
drwx—— 5 root root 4096 Dec 13 06:27 ..
drwxr-xr-x 3 root root 4096 Dec 13 04:26 27cf784147099545
drwxr-xr-x 3 root root 4096 Nov 22 06:52 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c
drwxr-xr-x 3 root root 4096 Dec 13 06:27 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9
drwxr-xr-x 3 root root 4096 Nov 22 06:52 b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc
drwx—— 3 root root 4096 Dec 13 06:27 _tmp
Docker爲這個鏡像分配了一個新的 ID:
91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9
這個新的鏡像已經被更新到了/var/lib/docker/repositories 而且能夠經過docker images命令來確認。
$ sudo cat /var/lib/docker/repositories | python -mjson.tool
{
「Repositories」: {
「scooby_snacks」: {
「latest」: 「91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9″
},
「ubuntu」: {
「12.04″: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「12.10″: 「b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc」,
「latest」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「precise」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「quantal」: 「b750fe79269d2ec9a3c593ef05b4332b1d1a02a62b4accb2c21d589ff2f5f2dc」
}
}
}
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
scooby_snacks latest 91acef3a5936 5 minutes ago 12.29 kB (virtual 131.3 MB)
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
讓咱們來看看文件/var/lib/docker/graph/91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9 的內容:
$ sudo cat /var/lib/docker/graph/91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9/json | python -mjson.tool
{
「Size」: 0,
「architecture」: 「x86_64″,
「config」: {
「AttachStderr」: false,
「AttachStdin」: false,
「AttachStdout」: false,
「Cmd」: null,
「CpuShares」: 0,
「Dns」: null,
「Domainname」: 「」,
「Entrypoint」: [],
「Env」: [
「HOME=/」,
「PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin」
],
「ExposedPorts」: {},
「Hostname」: 「86664242766c」,
「Image」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「Memory」: 0,
「MemorySwap」: 0,
「NetworkDisabled」: false,
「OpenStdin」: false,
「PortSpecs」: null,
「StdinOnce」: false,
「Tty」: false,
「User」: 「」,
「Volumes」: {},
「VolumesFrom」: 「」,
「WorkingDir」: 「」
},
「container」: 「86664242766c5548f8118716e873835c171811176a710e425c1fcf1fa367b505″,
「container_config」: {
「AttachStderr」: false,
「AttachStdin」: false,
「AttachStdout」: false,
「Cmd」: [
「/bin/sh」,
「-c」,
「touch scooby_snacks.txt」
],
「CpuShares」: 0,
「Dns」: null,
「Domainname」: 「」,
「Entrypoint」: [],
「Env」: [
「HOME=/」,
「PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin」
],
「ExposedPorts」: {},
「Hostname」: 「86664242766c」,
「Image」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」,
「Memory」: 0,
「MemorySwap」: 0,
「NetworkDisabled」: false,
「OpenStdin」: false,
「PortSpecs」: null,
「StdinOnce」: false,
「Tty」: false,
「User」: 「」,
「Volumes」: {},
「VolumesFrom」: 「」,
「WorkingDir」: 「」
},
「created」: 「2013-12-13T06:27:03.234029255Z」,
「docker_version」: 「0.6.7」,
「id」: 「91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9″,
「parent」: 「8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c」
}$ sudo cat /var/lib/docker/graph/91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9/layersize
12288$ sudo ls -al /var/lib/docker/graph/91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9/layer
total 16
drwxr-xr-x 4 root root 4096 Dec 13 06:27 .
drwxr-xr-x 3 root root 4096 Dec 13 06:27 ..
-rw-r–r– 1 root root 0 Dec 13 06:27 scooby_snacks.txt
-r–r–r– 1 root root 0 Dec 13 06:27 .wh..wh.aufs
drwx—— 2 root root 4096 Dec 13 06:27 .wh..wh.orph
drwx—— 2 root root 4096 Dec 13 06:27 .wh..wh.plnk
咱們對Dockerfile小小的修改,卻給編譯後的結果帶來了莫大的影響。另外須要注意的是Docker的鏡像文件裏只會記錄和parent image的差分信息,這也是理解layer概念的一個關鍵。
下面咱們就可使用咱們的新鏡像了。這裏咱們使用bash這個交互控制檯來操做。
$ docker run -i -t scooby_snacks /bin/bash
root@1f8602a7d589:/# ls -al
total 12308
drwxr-xr-x 30 root root 4096 Dec 13 06:43 .
drwxr-xr-x 30 root root 4096 Dec 13 06:43 ..
-rw——- 1 root root 208 Dec 13 06:43 .dockerenv
-rwxr-xr-x 1 root root 12516574 Nov 22 02:34 .dockerinit
drwxr-xr-x 2 root root 4096 Apr 11 2013 bin
drwxr-xr-x 2 root root 4096 Apr 19 2012 boot
drwxr-xr-x 6 root root 4096 Nov 22 06:52 dev
drwxr-xr-x 41 root root 4096 Nov 22 06:52 etc
drwxr-xr-x 2 root root 4096 Apr 19 2012 home
drwxr-xr-x 11 root root 4096 Nov 22 06:51 lib
drwxr-xr-x 2 root root 4096 Nov 22 06:51 lib64
drwxr-xr-x 2 root root 4096 Apr 11 2013 media
drwxr-xr-x 2 root root 4096 Apr 19 2012 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2013 opt
dr-xr-xr-x 102 root root 0 Dec 13 06:43 proc
drwx—— 2 root root 4096 Nov 22 06:51 root
drwxr-xr-x 4 root root 4096 Nov 22 06:51 run
drwxr-xr-x 2 root root 4096 Nov 22 06:51 sbin
-rw-r–r– 1 root root 0 Dec 13 06:27 scooby_snacks.txt
drwxr-xr-x 2 root root 4096 Mar 5 2012 selinux
drwxr-xr-x 2 root root 4096 Apr 11 2013 srv
dr-xr-xr-x 13 root root 0 Dec 13 06:43 sys
drwxrwxrwt 2 root root 4096 Apr 11 2013 tmp
drwxr-xr-x 10 root root 4096 Nov 22 06:51 usr
drwxr-xr-x 11 root root 4096 Nov 22 06:51 var
root@1f8602a7d589:/#
從上面的結果能夠看出,咱們在Dockerfile裏添加的以下一行:
RUN touch scooby_snacks.txt
在鏡像裏成功的建立了scooby_snacks.txt這個文件。
到目前爲止,咱們的全部操做都是基於本地的,沒有和外界進行任何交互。這很是重要,由於咱們能夠精心的準備一個完美的Dockerfile,直到咱們完成它爲止。如今,我以爲我已經完成了本地鏡像文件的製做,已經能夠發佈它了。
在進行發佈以前,你須要確保在官方網站建立了本身的帳號( make an account ),而後經過docker login來登陸進去。
$ docker login
Username: thoward
Password:
Email: thoward37@gmail.com
Login Succeeded
咱們經過docker push scooby_snacks命令來發布上面建立的鏡像文件。
$ docker push scooby_snacks
2013/12/13 06:49:36 Impossible to push a 「root」 repository. Please rename your repository in <user>/<repo> (ex: thoward/scooby_snacks)
從上面的消息能夠看出,Docker不容許咱們直接將鏡像發佈到根倉庫(root repository)下,咱們必須提供相似<user>/<repo>這樣的格式。
咱們須要從新構建咱們的鏡像,並指定用戶名屬性,命令爲 docker build -t thoward/scooby_snacks .(注意不要丟掉最後的點,表明當前文件夾)
$ docker build -t thoward/scooby_snacks .
Uploading context 64184320 bytes
Step 1 : FROM ubuntu
—> 8dbd9e392a96
Step 2 : RUN touch scooby_snacks.txt
—> Using cache
—> 91acef3a5936
Successfully built 91acef3a5936
Nice!上面的輸出裏有」Using cache」字眼,這說明Docker很聰明,知道咱們在此次鏡像構建中,並未作任何修改(除了名字),因此它不會真的從新再構建一遍的。
而後咱們就能夠從新發布鏡像了。固然,咱們須要指定正確的倉庫名稱:
$ docker push thoward/scooby_snacks
The push refers to a repository [thoward/scooby_snacks] (len: 1)
Sending image list
Pushing repository thoward/scooby_snacks (1 tags)
Pushing 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c
Image 8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c already pushed, skipping
Pushing tags for rev [8dbd9e392a964056420e5d58ca5cc376ef18e2de93b5cc90e868a1bbc8318c1c] on {https://registry-1.docker.io/v1/repositories/thoward/scooby_snacks/tags/latest}
Pushing 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9Pushing tags for rev [91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9] on {https://registry-1.docker.io/v1/repositories/thoward/scooby_snacks/tags/latest}
這樣,咱們就完成了鏡像的發佈工做。同時,咱們也能夠用docker search命令來查看這個鏡像。
$ docker search scooby_snacks
NAME DESCRIPTION STARS OFFICIAL TRUSTED
thoward/scooby_snacks 0
鏡像文件已經成功發佈了,下面咱們須要將剛纔沒有發佈成功的鏡像刪除。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
scooby_snacks latest 91acef3a5936 30 minutes ago 12.29 kB (virtual 131.3 MB)
thoward/scooby_snacks latest 91acef3a5936 30 minutes ago 12.29 kB (virtual 131.3 MB)
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)$ docker rmi scooby_snacks
Untagged: 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thoward/scooby_snacks latest 91acef3a5936 29 minutes ago 12.29 kB (virtual 131.3 MB)
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
上面的docker rmi命令就是刪除鏡像的命令。
不過,老實說咱們剛纔所發佈的鏡像對其餘人來講沒有任何意義,我也不想被別人當作菜鳥看待,因此我要刪掉它。
$ docker rmi thoward/scooby_snacks
Untagged: 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9
Deleted: 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
注意上面docker rmi命令的輸出,和以前的命令相比,此次多了一條Deleted: 91acef3a….的內容。這是由於Docker知道如今的系統裏沒有再對這個ID的鏡像的引用了,因此能夠刪除了,而不僅是僅僅刪除標籤(untagging)。
可是,docker rmi命令並不會Docker Index上刪除這個鏡像。咱們能夠測試下:
$ docker search scooby_snacks
NAME DESCRIPTION STARS OFFICIAL TRUSTED
thoward/scooby_snacks 0
不錯,它還在那裏。咱們能夠經過docker pull命令來下載它並繼續使用。
$ docker pull thoward/scooby_snacks
Pulling repository thoward/scooby_snacks
91acef3a5936: Download complete
8dbd9e392a96: Download complete$ docker run -i -t thoward/scooby_snacks /bin/bash
root@90f6546bf3b7:/# ls -al
total 12308
drwxr-xr-x 30 root root 4096 Dec 13 07:03 .
drwxr-xr-x 30 root root 4096 Dec 13 07:03 ..
-rw——- 1 root root 208 Dec 13 07:03 .dockerenv
-rwxr-xr-x 1 root root 12516574 Nov 22 02:34 .dockerinit
drwxr-xr-x 2 root root 4096 Apr 11 2013 bin
drwxr-xr-x 2 root root 4096 Apr 19 2012 boot
drwxr-xr-x 6 root root 4096 Nov 22 06:52 dev
drwxr-xr-x 41 root root 4096 Nov 22 06:52 etc
drwxr-xr-x 2 root root 4096 Apr 19 2012 home
drwxr-xr-x 11 root root 4096 Nov 22 06:51 lib
drwxr-xr-x 2 root root 4096 Nov 22 06:51 lib64
drwxr-xr-x 2 root root 4096 Apr 11 2013 media
drwxr-xr-x 2 root root 4096 Apr 19 2012 mnt
drwxr-xr-x 2 root root 4096 Apr 11 2013 opt
dr-xr-xr-x 105 root root 0 Dec 13 07:03 proc
drwx—— 2 root root 4096 Nov 22 06:51 root
drwxr-xr-x 4 root root 4096 Nov 22 06:51 run
drwxr-xr-x 2 root root 4096 Nov 22 06:51 sbin
-rw-r–r– 1 root root 0 Dec 13 06:27 scooby_snacks.txt
drwxr-xr-x 2 root root 4096 Mar 5 2012 selinux
drwxr-xr-x 2 root root 4096 Apr 11 2013 srv
dr-xr-xr-x 13 root root 0 Dec 13 07:03 sys
drwxrwxrwt 2 root root 4096 Apr 11 2013 tmp
drwxr-xr-x 10 root root 4096 Nov 22 06:51 usr
drwxr-xr-x 11 root root 4096 Nov 22 06:51 var
root@90f6546bf3b7:/#
看,咱們又從新使用這個鏡像。
不過有點不幸的是,命令行工具沒有提供從public index/registry上刪除鏡像的功能,咱們必須從官網的Web頁面上來刪除它。
首先,登陸進Docker的index網站( login via the web ),而後訪問要刪除的鏡像倉庫網址 https://index.docker.io/u/thoward/scooby_snacks/ 。
依次選擇’Settings’、 ‘Delete Repository’ 頁,而後點擊 ‘Delete Repo’ 按鈕。
在Web上刪除鏡像後,咱們再回到控制檯下,經過docker search scooby_snacks 命令來確認一下這個鏡像確實已經被刪除了。
$ docker search scooby_snacks
NAME DESCRIPTION STARS OFFICIAL TRUSTED
因爲咱們在本地從新pull過這個鏡像後沒有對它進行刪除操做,因此咱們還會在命令docker images中看到它,由於咱們保存着它的本地拷貝。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
thoward/scooby_snacks latest 91acef3a5936 46 minutes ago 12.29 kB (virtual 131.3 MB)
ubuntu 12.04 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu latest 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu precise 8dbd9e392a96 8 months ago 131.3 MB (virtual 131.3 MB)
ubuntu 12.10 b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
ubuntu quantal b750fe79269d 8 months ago 24.65 kB (virtual 179.7 MB)
若是想完全刪除這個鏡像,咱們須要再次執行docker rmi命令。
$ docker rmi thoward/scooby_snacks
Untagged: 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9
Deleted: 91acef3a5936769f763729529e736681e5079dc6ddf6ab0e61c327a93d163df9
辛辛苦苦製做的鏡像,就這麼被刪除了:-(。不過不用惋惜,咱們能夠輕鬆的經過Dockerfile再次建立一樣的鏡像出來。
在咱們作諸如上述工做的時候,不得不考慮安全上的問題。
即便你的Docker鏡像被從Docker索引服務器上刪除了,它也可能還在某人的機器裏存在着,並且對此你將無能爲力。
並且,正如咱們看到的那樣,位於本地的鏡像並非真正的「透明的二進制」文件。在Dockerfile文件裏設置的全部鏡像的內容都保存在JSON文件裏,Dockerfile裏命令執行所產生的物件(artifacts )也都被保存在層中,並做爲文件系統供咱們使用。若是你不當心將密碼或者key等敏感信息公開了,那麼你將沒法挽回這個錯誤,人們能夠像在開源代碼裏搜索東西同樣,很輕鬆的就發現這些信息。
對本身發佈的東西要萬分當心,若是一旦你的發佈裏包含了不應被他人看到的敏感信息,那麼首先要儘快下線該鏡像,而且更新全部使用了此敏感信息的全部相關係統。
總結
儘管Docker所使用的術語有時候會給用戶帶來必定的困惑,可是一旦你熟悉了上面的基本流程的話,在構建本身的鏡像的時候將會遊刃有餘,而且清楚的知道本身在何時,以何種方式來和他人分享你的成果。
譯者注:
1. 一些術語對照表:
layer : 層
build: 構建、編譯、建立,本文根據語境使用了這三種翻譯。
image:鏡像
index:索引或鏡像索引
respository:倉庫或鏡像倉庫
registry:註冊表或者鏡像註冊表
2. 參考資料:
官方術語index/registry:http://docs.docker.io/en/latest/api/registry_index_spec/