这组概念不多会让人产生疑惑,可是这二者的区别很是重要。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/