docker中容器的运行离不开image,一个image中都存放有哪些东西呢?这些东西又是以何种方式组织在一起的呢?今天让我们来撕开这层面纱,看看image到底是什么样。
撕
导出tar包
首先我们使用docker save
,将一个docker image保存成tar包,我们以nginx官方镜像
为例
1 | docker images |
走近nginx目录
现在nginx.tar
已经被解开了,接下来就要进入nginx目录一探究竟了。首先tree
一下nginx目录,看看都有什么文件。
1 | tree -L 2 ./nginx |
从目录结构上来看,有三个总体的描述文件repositories
、manifest.json
、4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b.json
,还有三个目录,这三个目录的结构基本相同都由json
、layer
、VERSION
组成。
通过这些名字,我们先简单猜测一下,image由很多layer组成,上层layer基于下层layer构建而成,下层layer基于基层layer构成。到底image是不是按我们的猜测构成的呢,让我们来看一看总体描述的三个文件。
manifest.json:1
{"Config":"4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b.json","RepoTags":["nginx:1.11.3"],"Layers":["80cdba09b091f72276c031bd64488c3da5f82022812bc995f0859abe0855a872/layer.tar","c575e5db41b92dbf9e1814b8ea9cf989ef650e37cfcef12fa402e630db6a581f/layer.tar","01d69dac180439f10b5f2f06b71fa19c9f89fb85cb5fd543dba9bb2ca9b620ef/layer.tar"]}]
通过manifest.json
文件我们可以看出,nginx:1.11.3
这个image的配置文件是4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b.json
,layer一共有三个分别是80cdba09b091f72276c031bd64488c3da5f82022812bc995f0859abe0855a872/layer.tar
,c575e5db41b92dbf9e1814b8ea9cf989ef650e37cfcef12fa402e630db6a581f/layer.tar
,01d69dac180439f10b5f2f06b71fa19c9f89fb85cb5fd543dba9bb2ca9b620ef/layer.tar
。
image的配置文件中都对image进行了哪些配置呢?让我们来看一看
4efb2fcdb1ab05fb03c9435234343c1cc65289eeb016be86193e88d3a5d84f6b.json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68{
"architecture":"amd64",
"author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"",
"config":{
"Hostname":"2da0903ff372",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"ExposedPorts":{"443/tcp":{},"80/tcp":{}},
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","NGINX_VERSION=1.11.3-1~jessie"],
"Cmd":["nginx","-g","daemon off;"],
"ArgsEscaped":true,
"Image":"sha256:27ca9d70a764c6955e354f5fdc706b03ed47601213ac9fc638a8943fcc7680f8",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":[],
"Labels":{}
},
"container":"25ab8b143580751e438246801e7ba720f6f84ee9faca3522532e7fbe1ed7021f",
"container_config":{
"Hostname":"2da0903ff372",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"ExposedPorts":{"443/tcp":{},"80/tcp":{}},
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","NGINX_VERSION=1.11.3-1~jessie"],
"Cmd":["/bin/sh","-c","#(nop) CMD [\"nginx\" \"-g\" \"daemon off;\"]"],
"ArgsEscaped":true,
"Image":"sha256:27ca9d70a764c6955e354f5fdc706b03ed47601213ac9fc638a8943fcc7680f8",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":[],
"Labels":{}
},
"created":"2016-08-23T18:51:23.709520142Z",
"docker_version":"1.10.3",
"history":[
{"created":"2016-07-28T17:47:54.990622865Z","created_by":"/bin/sh -c #(nop) ADD file:0e0565652aa852f62033d99f84892216020d30f64521ded5e72d4940bc4c9697 in /"},
{"created":"2016-07-28T17:47:55.809686499Z","created_by":"/bin/sh -c #(nop) CMD [\"/bin/bash\"]","empty_layer":true},
{"created":"2016-08-23T18:49:31.945397165Z","author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"","created_by":"/bin/sh -c #(nop) MAINTAINER NGINX Docker Maintainers \"docker-maint@nginx.com\"","empty_layer":true},
{"created":"2016-08-23T18:49:33.057946615Z","author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"","created_by":"/bin/sh -c #(nop) ENV NGINX_VERSION=1.11.3-1~jessie","empty_layer":true},
{"created":"2016-08-23T18:51:19.236946594Z","author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"","created_by":"/bin/sh -c apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \t\u0026\u0026 echo \"deb http://nginx.org/packages/mainline/debian/ jessie nginx\" \u003e\u003e /etc/apt/sources.list \t\u0026\u0026 apt-get update \t\u0026\u0026 apt-get install --no-install-recommends --no-install-suggests -y \t\t\t\t\t\tca-certificates \t\t\t\t\t\tnginx=${NGINX_VERSION} \t\t\t\t\t\tnginx-module-xslt \t\t\t\t\t\tnginx-module-geoip \t\t\t\t\t\tnginx-module-image-filter \t\t\t\t\t\tnginx-module-perl \t\t\t\t\t\tnginx-module-njs \t\t\t\t\t\tgettext-base \t\u0026\u0026 rm -rf /var/lib/apt/lists/*"},
{"created":"2016-08-23T18:51:21.574094006Z","author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"","created_by":"/bin/sh -c ln -sf /dev/stdout /var/log/nginx/access.log \t\u0026\u0026 ln -sf /dev/stderr /var/log/nginx/error.log"},
{"created":"2016-08-23T18:51:22.632895061Z","author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"","created_by":"/bin/sh -c #(nop) EXPOSE 443/tcp 80/tcp","empty_layer":true},
{"created":"2016-08-23T18:51:23.709520142Z","author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"","created_by":"/bin/sh -c #(nop) CMD [\"nginx\" \"-g\" \"daemon off;\"]","empty_layer":true}
],
"os":"linux",
"rootfs":{
"type":"layers",
"diff_ids":[
"sha256:2f71b45e4e254ddceb187b1467f5471f0e14d7124ac2dd7fdd7ddbc76e13f0e5",
"sha256:d7953e5e5bba5c637ce6eb81a4528a777c4265386cb12e9bff8124ef97538746",
"sha256:69ecf026ff94793ab573754612e6fa40b28331a47c3584de0b32d39a88959c37"
]
}
}
看完这个配置文件我惊到了,如此庞大的一个配置文件告诉我们dockerfile能配的我能配,dockerfile不能配的我也能配。。。这个配置文件具体就不分析了。。。
刚刚看完那个累心的配置文件,接下来让我们来说说这三个layer,哪一个layer是入口呢?
repositories:1
{"nginx":{"1.11.3":"01d69dac180439f10b5f2f06b71fa19c9f89fb85cb5fd543dba9bb2ca9b620ef"}}
我们通过查看repositories
可以看出1.11.3
这个版本的layer入口是01d69dac180439f10b5f2f06b71fa19c9f89fb85cb5fd543dba9bb2ca9b620ef
。那么三个layer之间的依赖关系怎样呢?让我们进入各个layer一探究竟吧。
layer 01d69dac180439f10b5f2f06b71fa19c9f89fb85cb5fd543dba9bb2ca9b620ef
该layer中的json
文件描述的本layer的配置信息
json:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52{
"id":"01d69dac180439f10b5f2f06b71fa19c9f89fb85cb5fd543dba9bb2ca9b620ef",
"parent":"c575e5db41b92dbf9e1814b8ea9cf989ef650e37cfcef12fa402e630db6a581f",
"created":"2016-08-23T18:51:23.709520142Z",
"container":"25ab8b143580751e438246801e7ba720f6f84ee9faca3522532e7fbe1ed7021f",
"container_config":{
"Hostname":"2da0903ff372",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"ExposedPorts":{"443/tcp":{},"80/tcp":{}},
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","NGINX_VERSION=1.11.3-1~jessie"],
"Cmd":["/bin/sh","-c","#(nop) CMD [\"nginx\" \"-g\" \"daemon off;\"]"],
"ArgsEscaped":true,
"Image":"sha256:27ca9d70a764c6955e354f5fdc706b03ed47601213ac9fc638a8943fcc7680f8",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":[],
"Labels":{}
},
"docker_version":"1.10.3",
"author":"NGINX Docker Maintainers \"docker-maint@nginx.com\"",
"config":{
"Hostname":"2da0903ff372",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"ExposedPorts":{"443/tcp":{},"80/tcp":{}},
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","NGINX_VERSION=1.11.3-1~jessie"],
"Cmd":["nginx","-g","daemon off;"],
"ArgsEscaped":true,
"Image":"sha256:27ca9d70a764c6955e354f5fdc706b03ed47601213ac9fc638a8943fcc7680f8",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":[],
"Labels":{}
},
"architecture":"amd64",
"os":"linux"
}
我们可以看到parent
字段指出了当前layer的父layer是c575e5db41b92dbf9e1814b8ea9cf989ef650e37cfcef12fa402e630db6a581f
。
当前layer中数据内容请见layer.tar
layer.tar:1
2
3
4
5
6
7 tree ./layer
./layer
└── var
└── log
└── nginx
├── access.log -> /dev/stdout
└── error.log -> /dev/stderr
layer c575e5db41b92dbf9e1814b8ea9cf989ef650e37cfcef12fa402e630db6a581f
该layer中的json
文件描述的本layer的配置信息
json:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24{
"id":"c575e5db41b92dbf9e1814b8ea9cf989ef650e37cfcef12fa402e630db6a581f",
"parent":"80cdba09b091f72276c031bd64488c3da5f82022812bc995f0859abe0855a872",
"created":"1970-01-01T08:00:00+08:00",
"container_config":{
"Hostname":"",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":null,
"Cmd":null,
"Image":"",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":null,
"Labels":null
}
}
该layer中的父layer是80cdba09b091f72276c031bd64488c3da5f82022812bc995f0859abe0855a872
当前layer中的数据内容请见layer.tar
layer.tar:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 tree -L 2 ./layer
./layer
├── etc
│ ├── alternatives
│ ├── apt
│ ├── ca-certificates
│ ├── ca-certificates.conf
│ ├── default
│ ├── fonts
│ ├── group
│ ├── group-
│ ├── gshadow
│ ├── gshadow-
│ ├── init.d
│ ├── ld.so.cache
│ ├── logrotate.d
│ ├── nginx
│ ├── passwd
│ ├── passwd-
│ ├── perl
│ ├── rc0.d
│ ├── rc1.d
│ ├── rc2.d
│ ├── rc3.d
│ ├── rc4.d
│ ├── rc5.d
│ ├── rc6.d
│ ├── shadow
│ ├── shadow-
│ ├── ssl
│ ├── subgid
│ ├── subgid-
│ ├── subuid
│ ├── subuid-
│ └── ucf.conf
├── lib
│ └── x86_64-linux-gnu
├── tmp
├── usr
│ ├── bin
│ ├── lib
│ ├── local
│ ├── sbin
│ └── share
└── var
├── cache
├── lib
└── log
layer 80cdba09b091f72276c031bd64488c3da5f82022812bc995f0859abe0855a872
该layer中的json
文件描述的本layer的配置信息
json:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23{
"id":"80cdba09b091f72276c031bd64488c3da5f82022812bc995f0859abe0855a872",
"created":"1970-01-01T08:00:00+08:00",
"container_config":{
"Hostname":"",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":null,
"Cmd":null,
"Image":"",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":null,
"Labels":null
}
}
从配置中可以看出,没有parent
字段了。说明这个layer应该就是base layer了。(我十分好奇nginx镜像是用哪个基础镜像做出来的?)
当前layer中的数据内容请见layer.tar
layer.tar:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 tree -L 1 ./layer
./layer
├── bin
├── boot
├── dev
├── etc
├── home
├── lib
├── lib64
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin
├── srv
├── sys
├── tmp
├── usr
└── var
1 | cat ./layer/etc/debian_version |
噢,原来nginx镜像是基于debian 8.5做出来的。