
Linux Kernel中的Namespaces解决了进程、网络以及文件系统等资源的隔离,Cgroups实现了CPU、内存的限制,但是在Docker还有一个非常重要的问题需要解决 — 那就是image(镜像)
Docker镜像的本质就是一个压缩包,我们可以使用docker export 命令将一个Docker镜像中的文件导出
[root@kube-master01 nginx]#
[root@kube-master01 nginx]# docker export $(docker create nginx:1.17.6-alpine) | tar -C ./ -xf -
[root@kube-master01 nginx]# ls
bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
[root@kube-master01 nginx]#
可以看到NGINX镜像中的目录结构与Linux操作系统的根目录中并没有太多的区别,Linux之上皆文件,Docker镜像就是一个文件。
Union File System简称为UnionFS,在Linux中用于把多个文件(目录)『联合』到同一个挂载点的文件系统服务,这些文件(目录)称为层或分支,整个『联合』的过程被称为联合挂载(Union Mount)
[root@kube-master01 demo]# tree
.
|-- admin
| `-- admin.logs
|-- system
| `-- system.logs
|-- test
| `-- test.logs
`-- unionfs
4 directories, 3 files
[root@kube-master01 demo]# mount -t overlay -o lowerdir=./system:./admin:./test none ./unionfs
[root@kube-master01 demo]# df -k
Filesystem 1K-blocks Used Available Use% Mounted on
devtmpfs 997360 0 997360 0% /dev
tmpfs 1018616 24 1018592 1% /dev/shm
tmpfs 1018616 548 1018068 1% /run
tmpfs 1018616 0 1018616 0% /sys/fs/cgroup
/dev/vda1 51473888 24098560 24737580 50% /
tmpfs 203724 0 203724 0% /run/user/0
none 51473888 24098560 24737580 50% /root/demo/unionfs
[root@kube-master01 demo]# ls -lrt ./unionfs/
total 12
-rw-r--r-- 1 root root 5 Dec 3 00:05 test.logs
-rw-r--r-- 1 root root 5 Dec 3 00:05 system.logs
-rw-r--r-- 1 root root 5 Dec 3 00:05 admin.logs
[root@kube-master01 demo]#
目前overlay2替代AUFS成为Docker推荐的存储驱动程序,本文皆采用overlay2示例
Docker镜像和Docker容器

下层是镜像层,叫做lowerdir,上层是容器层,叫做upperdir。对外展示的统一视图称作merged。
在Docker中,所有镜像层和容器层的文件都存储在 /var/lib/docker/存储驱动/ 目录中
image目录是专门用来存储元数据(imagedb和layerdb),image由多个layer组合而成的,换句话说layer就是一个资源池,如果有多个image会指向同一个layer,那么这一个layer称为公共层。
[root@kube-master01 ~]# ls /var/lib/docker/image/overlay2/
distribution imagedb layerdb repositories.json
[root@kube-master01 ~]#
imagedb/content/sha256/目录下存储所有镜像的详情,以镜像ID开头进行区分,可以在rootfs项看到nginx:1.17.6-alpine与nginx:1.17.6-alpine有一层layers是共享的
[root@kube-master01 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx 1.17.6-alpine a624d888d69f 12 days ago 21.5MB
nginx 1.17.5-alpine b6753551581f 5 weeks ago 21.4MB
[root@kube-master01 ~]# ls /var/lib/docker/image/overlay2/imagedb/content/sha256/a624d888d69f*
/var/lib/docker/image/overlay2/imagedb/content/sha256/a624d888d69ffdc185ed3b9c9c0645e8eaaac843ce59e89f1fbe45b0581e4ef6
[root@kube-master01 ~]# ls /var/lib/docker/image/overlay2/imagedb/content/sha256/b6753551581f*
/var/lib/docker/image/overlay2/imagedb/content/sha256/b6753551581f2d2fb976dd502f15764526d423b23cb3f5518c0a34c98451cec9
[root@kube-master01 ~]# cat /var/lib/docker/image/overlay2/imagedb/content/sha256/a624d888d69ffdc185ed3b9c9c0645e8eaaac843ce59e89f1fbe45b0581e4ef6 | jq . | tail -n 10
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
"sha256:f4cef7054e837eb301d4c669bf2b58b3f764188d4a8e20dd65fcbfa4d7f688a1"
]
}
}
[root@kube-master01 ~]# cat /var/lib/docker/image/overlay2/imagedb/content/sha256/b6753551581f2d2fb976dd502f15764526d423b23cb3f5518c0a34c98451cec9 | jq . | tail -n 10
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:77cae8ab23bf486355d1b3191259705374f4a11d483b24964d2f729dd8c076a0",
"sha256:bba7d2385bc1fa532ccca27efa3ce6b5ae200ef720ad7461c9ba9821c34cced1"
]
}
}
[root@kube-master01 ~]#
/var/lib/docker/image/overlay2/只是存储元数据,所有镜像层的文件存储在/var/lib/docker/overlay2/,同时该目录包含镜像或容器层的挂载点,最终会被 Docker通过联合的方式进行挂载组装。
[root@kube-master01 ~]# docker run -d nginx:1.17.6-alpine
fff4041bb9e8cc98a9e5f50876619932ebd0b9e7644ff55d7e96d50b4916ddf5
[root@kube-master01 ~]# cat /var/lib/docker/image/overlay2/layerdb/mounts/fff4041bb9e8cc98a9e5f50876619932ebd0b9e7644ff55d7e96d50b4916ddf5/init-id
5d14ebeab22dbd6bee9040188c9cc20c78f01de3f26fd4f707f7c87d9de9bea2-init
[root@kube-master01 ~]# cat /var/lib/docker/image/overlay2/layerdb/mounts/fff4041bb9e8cc98a9e5f50876619932ebd0b9e7644ff55d7e96d50b4916ddf5/mount-id
5d14ebeab22dbd6bee9040188c9cc20c78f01de3f26fd4f707f7c87d9de9bea2
// 所有初始化的容器层的文件都存储在/var/lib/docker/overlay2/$init-id/diff/目录中
[root@kube-master01 ~]# ls /var/lib/docker/overlay2/5d14ebeab22dbd6bee9040188c9cc20c78f01de3f26fd4f707f7c87d9de9bea2-init/diff/
dev etc
// 所有容器运行层的文件存储在/var/lib/docker/overlay2/$mount-id/diff/目录中
[root@kube-master01 ~]# ls /var/lib/docker/overlay2/5d14ebeab22dbd6bee9040188c9cc20c78f01de3f26fd4f707f7c87d9de9bea2/diff/
run var
[root@kube-master01 ~]#
我们都知道docker镜像是分层的,Dockerfile中一个命令代表一层,相同的层是共享的,每一个镜像层都是建立在另一个镜像层之上的,同时所有的镜像层都是只读的,所有的容器都建立在Kernel上之上,内核为之提供Namespace、Cgroups、rootfs等支持

当镜像被 docker run 命令创建时就会在镜像的最上层(CMD层之上上)添加一个可写的层,称为容器层,所有对于运行时容器的修改都是对这个该层的修改。所以容器和镜像的区别就在于:所有的镜像都是只读的,而容器在镜像加上一个可读写的层,也就是同一个镜像可以对应多个容器。
[root@kube-master01 ~]# docker history nginx:1.17.6-alpine
IMAGE CREATED CREATED BY SIZE COMMENT
a624d888d69f 12 days ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
<missing> 12 days ago /bin/sh -c #(nop) STOPSIGNAL SIGTERM 0B
<missing> 12 days ago /bin/sh -c #(nop) EXPOSE 80 0B
<missing> 12 days ago /bin/sh -c set -x && addgroup -g 101 -S … 15.9MB
<missing> 12 days ago /bin/sh -c #(nop) ENV PKG_RELEASE=1 0B
<missing> 12 days ago /bin/sh -c #(nop) ENV NJS_VERSION=0.3.7 0B
<missing> 12 days ago /bin/sh -c #(nop) ENV NGINX_VERSION=1.17.6 0B
<missing> 5 weeks ago /bin/sh -c #(nop) LABEL maintainer=NGINX Do… 0B
<missing> 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
<missing> 5 weeks ago /bin/sh -c #(nop) ADD file:fe1f09249227e2da2… 5.55MB
[root@kube-master01 ~]#
1958年的慕尼黑空难让曼联战队瞬间消失在夜空,幸存下来的曼联队的主帅马特·巴斯比用血泪和汗水重建曼联。10年之后,巴斯比带领曼联捧起了欧冠,以告慰故去的亡魂!而这座Holy Trinity雕像也变成了永恒的纪念!
信仰、坚持、重生…希望在前进征途正在不懈拼搏的你,也能够拥有自己的信仰和希望,即便要途径无数沙漠和海洋,也能在经历千帆后柳暗花明!

往期回顾
走进Container: 资源的限制
走进Container: 资源的隔离






