1. Docker 镜像
1.1. 什么是 Docker 镜像?
镜像的英语翻译一般可以翻译为 mirror
或 image
。
"镜像" : 是一个名词,字面意思是一面镜子照应出的图像;字典解释为其各部分的排列与另一个作为模型的基本相似的东西的排列正相反;相对一根与之交错的轴或一个与之交错的平面为颠倒的东西。狭义上可以理解为基于一个模板复制出的具有相同属性的一个副本。
按照狭义的理解镜像:
- 克隆的对象
- 复制的副本
- 模板的实例
- 磨具生产的物品
- 软件COPY的副本
- 操作系统ISO镜像
- 虚拟机的镜像
Docker 镜像核心概念类似,就像一个软件包的复制,只是有了特殊场景下的限定,使其概念和功能更加的具体。
Docker 镜像是将一层或多层存储层按照一定文件组织格式打包成一个只读的新文件,该文件能够作为容器运行时基础,提供容器运行依赖的相关文件.
1.2. 镜像的原理
1.2.1. Docker 镜像具有以下特点:
- 类似操作系统的ISO文件
- 类似系统进程启动的软件包
- Docker 镜像是只读的
- Docker 使用了UTFS文件系统特性
- Docker 镜像作为容器启动的模板
1.2.2. Docker 镜像分层
1.2.3. Docker 镜像的来源获取:
1.3. Docker 镜像的组成
Docker 镜像是由多层的其他镜像和配置组成,采用分层结构的做大好处是“共享资源。
使用镜像开启并运行一个容器 镜像作为开启容器的模板。使用镜像创建并且运行一个容器,就是在镜像层的最上层添加一层容器层。所有的镜像层都是只读的容器层是可写的,容器开启之后,所有的修改该作都保存在可写的容器层。
容器以下所有镜像曾都是只读的,docker查找文件时是从上往下依次查找;容器层用来保存镜像变化的部分,并不会对镜像本身进行任何修改;一个镜像最多可以有127层
docker 容器进行可写时,是在可写容器层进行可写动作,经底层镜像层的文件会先复制到可写层再执行删除、创建等动作
2. 镜像的文件组织
例如,centos:7 镜像是通过对应版本的 Dockerfile 来进行 build 构建
docker 使用 overlay2 的驱动
2.1. Dockerfile 构建镜像
Centos 社区维护的一个 X86_64 的镜像 Dockerfile
内容如下:
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
从该 Dockerfile 中可以参考,CentOS7 镜像构建是核心是基于 rootfs 的打包文件 centos-7-x86_64-docker.tar.xz 结合一些 Label 配置标签来构建的,内容非常基础。
[!TIP|style:flat]
FROM scratch
基础镜像是一个空的镜像,没有任何内容的镜像。对于基础操作系统镜像和 golang 类型的没有其他依赖的应用比较合适。
基于该 Dockerfile 构建出的镜像历史
$ sudo docker history centos:7
IMAGE CREATED CREATED BY SIZE COMMENT
eeb6ee3f44bd 8 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 8 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B
<missing> 8 months ago /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4… 204MB
镜像下载到本地后可以通过 docker images
查看和 docker run
等命令来使用镜像。镜像在本地是怎么存储是通过
2.2. docker images 镜像信息查看
docker images
会显示当前主机上所有的容器镜像列表
# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
centos 7 eeb6ee3f44bd 8 months ago 204MB
执行 docker images
查看时会读取 repositories.json
中的内容,按照 output 的格式输出显示。
默认没有指定具体镜像 TAG 或 ID 时,会显示所有的镜像列表。
- /var/lib/docker/image/overlay2/repositories.json
{
"Repositories":{
"centos":{
"centos:7":"sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9",
"centos@sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407":"sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9"
}
}
}
当使用 docker inspect
或 docker run
等命令查看和运行指定的镜像时,会通过 repositories.json 中对应的 sha256 查找镜像的详细信息
- /var/lib/docker/image/overlay2/imagedb/content/sha256/ eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9
{
"architecture":"amd64",
"config":{
"Hostname":"",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":[
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd":[
"/bin/bash"
],
"Image":"sha256:ba35a4b787c8f11e3b6ed9248c7663b4f27459e9715a1ace09f966259d5ebc3a",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":null,
"Labels":{
"org.label-schema.build-date":"20201113",
"org.label-schema.license":"GPLv2",
"org.label-schema.name":"CentOS Base Image",
"org.label-schema.schema-version":"1.0",
"org.label-schema.vendor":"CentOS",
"org.opencontainers.image.created":"2020-11-13 00:00:00+00:00",
"org.opencontainers.image.licenses":"GPL-2.0-only",
"org.opencontainers.image.title":"CentOS Base Image",
"org.opencontainers.image.vendor":"CentOS"
}
},
"container":"5e4c7bfd35862166e9efd7532208300600114f0acff8f82fd537a57bdd523fe2",
"container_config":{
"Hostname":"5e4c7bfd3586",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":[
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd":[
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/bin/bash\"]"
],
"Image":"sha256:ba35a4b787c8f11e3b6ed9248c7663b4f27459e9715a1ace09f966259d5ebc3a",
"Volumes":null,
"WorkingDir":"",
"Entrypoint":null,
"OnBuild":null,
"Labels":{
"org.label-schema.build-date":"20201113",
"org.label-schema.license":"GPLv2",
"org.label-schema.name":"CentOS Base Image",
"org.label-schema.schema-version":"1.0",
"org.label-schema.vendor":"CentOS",
"org.opencontainers.image.created":"2020-11-13 00:00:00+00:00",
"org.opencontainers.image.licenses":"GPL-2.0-only",
"org.opencontainers.image.title":"CentOS Base Image",
"org.opencontainers.image.vendor":"CentOS"
}
},
"created":"2021-09-15T18:20:23.99863383Z",
"docker_version":"20.10.7",
"history":[
{
"created":"2021-09-15T18:20:23.417639551Z",
"created_by":"/bin/sh -c #(nop) ADD file:b3ebbe8bd304723d43b7b44a6d990cd657b63d93d6a2a9293983a30bfc1dfa53 in / "
},
{
"created":"2021-09-15T18:20:23.819893035Z",
"created_by":"/bin/sh -c #(nop) LABEL org.label-schema.schema-version=1.0 org.label-schema.name=CentOS Base Image org.label-schema.vendor=CentOS org.label-schema.license=GPLv2 org.label-schema.build-date=20201113 org.opencontainers.image.title=CentOS Base Image org.opencontainers.image.vendor=CentOS org.opencontainers.image.licenses=GPL-2.0-only org.opencontainers.image.created=2020-11-13 00:00:00+00:00",
"empty_layer":true
},
{
"created":"2021-09-15T18:20:23.99863383Z",
"created_by":"/bin/sh -c #(nop) CMD [\"/bin/bash\"]",
"empty_layer":true
}
],
"os":"linux",
"rootfs":{
"type":"layers",
"diff_ids":[
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02"
]
}
}
这个 json 文件的内容和 docker inspect
查看镜像的详细信息内容是一样的。
$ sudo docker inspect centos:7
在详细信息内容中有比较多的信息,其中和镜像文件相关的主要是 rootfs 字段
"rootfs":{
"type":"layers",
"diff_ids":[
"sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02"
]
}
rootfs 字段的 sha256 值与 /var/lib/docker/image/overlay2/layerdb/sha256
目录进行关联
在该目录中有这个镜像层的详细信息
# ls /var/lib/docker/image/overlay2/layerdb/sha256/174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02/
cache-id diff size tar-split.json.gz
该目录中包含该 rootfs 的相关的信息,其中 diff、merge、upper 目录是 overlay 的数据目录。
- diff 里面存储了这一层所包含的文件。
- link中存储的是这一层所对应的/var/lib/docker/overlay2/l/中的软连接。
- lower文件中存储的是这一层所依赖的低层。它们用冒号隔开,每一条记录都是指向/var/lib/docker/overlay2/l/ 中的软连接。
lowerdir:表示较为底层的目录,修改联合挂载点不会影响到lowerdir。 upperdir:表示较为上层的目录,修改联合挂载点会在upperdir同步修改。 merged:是lowerdir和upperdir合并后的联合挂载点。 workdir:用来存放挂载后的临时文件与间接文件。
当文件被修改后,会在 diff 中保留差异
其中基础的底层文件通过 cache-id 中的 sha256 与 /var/lib/docker/overlay2/
目录关联
/var/lib/docker/image/overlay2/layerdb/sha256/174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02 # cat cache-id
80d7b6505daa873f286803813c64a3af75510cd07614378928c8c6af5a3411c6
- 实际的数据路径
/var/lib/docker/overlay2/80d7b6505daa873f286803813c64a3af75510cd07614378928c8c6af5a3411c6 # ls
diff link
2.3. 其他镜像信息
一个镜像 TAG 只能与一个镜像对应,而一个镜像可以有多个不同的 tag,这些 tag 的信息保存在
/var/lib/docker/image/overlay2/distribution/v2metadata-by-diffid/sha256 # cat 174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02
[{"Digest":"sha256:2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc","SourceRepository":"docker.io/library/centos","HMAC":""}]
/var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256 # cat 2d473b07cdd5f0912cd6f1a703352c82b512407db6b05b43f2553732b55df3bc
sha256:174f5685490326fc0a1c0f5570b8663732189b327007e47ff13d2ca59673db02
3. 容器
/ # docker run -itd --name centos7 centos:7
9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd
/ # docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9851c7a6cf5e centos:7 "/bin/bash" 26 seconds ago Up 25 seconds centos7
查看容器的详细信息
docker inspect 查看的主要内容来源
- /var/lib/docker/containers/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd/config.v2.json
/ # docker inspect 9851c7a6cf5e
[
{
"Id": "9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd",
"Created": "2022-05-19T05:43:53.303358428Z",
"Path": "/bin/bash",
"Args": [],
"State": {
......
},
"Image": "sha256:eeb6ee3f44bd0b5103bb561b4c16bcb82328cfe5809ab675bb17ab3a16c517c9",
"ResolvConfPath": "/var/lib/docker/containers/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd/hostname",
"HostsPath": "/var/lib/docker/containers/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd/hosts",
"LogPath": "/var/lib/docker/containers/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd-json.log",
"Name": "/centos7",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
...... // 内容来源 /var/lib/docker/containers/9851c7a6cf5e809d1a9762bace5fc5276cf34366af9a7eb2e6ad7dd21f41c3bd/hostconfig.json
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09-init/diff:/var/lib/docker/overlay2/80d7b6505daa873f286803813c64a3af75510cd07614378928c8c6af5a3411c6/diff",
"MergedDir": "/var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09/merged",
"UpperDir": "/var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09/diff",
"WorkDir": "/var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09/work"
},
"Name": "overlay2"
},
"Mounts": [],
"Config": {
......
},
"NetworkSettings": {
......
}
}
]
容器创建了新的 overaly2 目录
- 3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09
/var/lib/docker/overlay2 # ls -lha
total 24K
drwx--x--- 6 root root 4.0K May 19 05:43 .
drwx--x--- 14 root root 4.0K May 17 02:31 ..
drwx--x--- 5 root root 4.0K May 19 05:43 3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09
drwx--x--- 4 root root 4.0K May 19 05:43 3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09-init
drwx--x--- 3 root root 4.0K May 19 05:43 80d7b6505daa873f286803813c64a3af75510cd07614378928c8c6af5a3411c6
drwx------ 2 root root 4.0K May 19 05:43 l
挂载
$ mount |grep overlay
overlay on / type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/5XCLM6JQYXXOAOV3AQQ77KCI66:/var/lib/docker/overlay2/l/FA6Y5AFH5GNXWDPKLFME6UEKFP:/var/lib/docker/overlay2/l/Z6AT7TLOJLCFJO7ZIPCG7LMBXX:/var/lib/docker/overlay2/l/FWHKPBJE45K2YE2OSEW4ZHKGEE:/var/lib/docker/overlay2/l/YFGVUAX3ZSCD2WBBWPHBQBD6QB:/var/lib/docker/overlay2/l/EZ2G3YW3WAHWZXUZBPK3F4AIJH:/var/lib/docker/overlay2/l/USBF7WYROZLQWZRBREJMHNOBXI:/var/lib/docker/overlay2/l/3LOL6HHKNEQWEDSY3U63RYRM6C:/var/lib/docker/overlay2/l/Q6SSBA7LNHRNRK25V3JWG72PMF:/var/lib/docker/overlay2/l/A2CXTSQJ773RRXR6JLDZTNX57C:/var/lib/docker/overlay2/l/KF4E74Y4ZORBKE77IJRP2KKPJL:/var/lib/docker/overlay2/l/4QQTITRRE5EKV42VCZL6AX5SGJ:/var/lib/docker/overlay2/l/ZQYQBJMQ7MDYB5HXJPYRJF6WV7:/var/lib/docker/overlay2/l/QML2ZGFSOIVF4X3WJR2RTCUQ2O,upperdir=/var/lib/docker/overlay2/21244873a105c8ec1f19da8e9460f722c8256946acf981d5e9df7d29d9986c13/diff,workdir=/var/lib/docker/overlay2/21244873a105c8ec1f19da8e9460f722c8256946acf981d5e9df7d29d9986c13/work)
overlay on /var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/USRHV2PI3SGJ6R5U7TARGVONK4:/var/lib/docker/overlay2/l/W6EYYACVENB43LD2XRMTHG2HHZ,upperdir=/var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09/diff,workdir=/var/lib/docker/overlay2/3a2af280a3b92e0201c91f2599f319117bf1aa61aebf6dacd945d6a296674f09/work)