【Docker进阶-03】存储原理
docker不止 基于 AUFS(联合文件系统);docker现在在底层使用自己的存储驱动storage drivers, 来组件文件内容 。
目前是采用:The copy-on-write (CoW) strategy写时复制技术【https:// docs.docker.com/engine/storage/drivers/】
思考
镜像(Image):固定不变的。一个镜像可以启动很多容器
容器(Container):文件系统可能经常变化(比如logs)
问题:
- 容器: 某个软件完整的运行环境;包含了一个小型的linux系统
- 宿主机里面同时4个nginx;一个nginx运行时完整环境有20MB
- 4个nginx 合起来占用多少的磁盘空间
- 80?这种计算方式,一定会很大...
nginx这个镜像怎么存的
bash
docker image inspect nginx 指示了镜像怎么存的

LowerDir
底层目录; 包含小型 linux和装好的软件

倒着看:
-
小linux系统(FROM apline) + Dockerfile的每一个命令可能都引起了系统的修改。【和git一样,只记录变化】
-
ls -i,该图片展示的是镜像的底层文件的inode

-
我们进入到这个镜像启动的容器,会发现容器的文件系统就是镜像的;
docker ps -s;可以看到这个容器真正用到的文件大小 -
容器也会自己建立层;如果想要改东西,把改的内容复制到容器层即可;
docker inspect container

MergedDir
合并目录;容器最终的完整工作目录全内容都在合并层;数据卷在容器层产生;所有的增删改都在容器层;

UpperDir
上层目录;
WorkDir
工作目录(临时层)
总结
docker底层的 storage driver完成了以上的目录组织结构


镜像如何存储
Images and layers
截取的nginx的分层:

Docker镜像由一系列层组成。 每层代表镜像的Dockerfile中的一条指令。 除最后一层外的每一层都是只读的。 如以下Dockerfile,Dockerfile文件里面几句话,镜像就有几层

该Dockerfile包含四个命令,每个命令创建一个层。
-
FROM语句从ubuntu:15.04映像创建一个图层开始。
-
COPY命令从Docker客户端的当前目录添加一些文件。
-
RUN命令使用make命令构建您的应用程序。
-
最后,最后一层指定要在容器中运行的命令。
每一层只是与上一层不同的一组。 这些层彼此堆叠。
创建新容器时,可以在基础层之上添加一个新的可写层。 该层通常称为"容器层"。 对运行中的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此可写容器层

Container and layers
容器和镜像之间的主要区别是可写顶层。
在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。
删除容器后,可写层也会被删除。 基础图像保持不变。 因为每个容器都有其自己的可写容器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对同一基础映像的访问,但具有自己的数据状态。
下图显示了共享同一Ubuntu 15.04映像的多个容器:

磁盘容量预估
bash
docker ps -s
size:用于每个容器的可写层的数据量(在磁盘上)。
virtual size:容器使用的用于只读图像数据的数据量加上容器的可写图层大小。
多个容器可以共享部分或全部只读图像数据。
从同一图像开始的两个容器共享100%的只读数据,而具有不同图像的两个容器(具有相同的层)共享这些公共层。 因此,不能只对虚拟大小进行总计。这高估了总磁盘使用量,可能是一笔不小的数目。
镜像如何挑选
busybox:是一个集成了一百多个最常用Linux命令和工具的软件。linux工具里的瑞士军刀
alpine:Alpine操作系统是一个面向安全的轻型Linux发行版经典最小镜像,基于busybox,功能比Busybox完善。
slim:docker hub中有些镜像有slim标识,都是瘦身了的镜像。也要优先选择
无论是制作镜像还是下载镜像,优先选择alpine类型.
Copy On Write
写时复制是一种共享和复制文件的策略,可最大程度地提高效率。
如果文件或目录位于映像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使用现有文件。
另一层第一次需要修改文件时(在构建映像或运行容器时),将文件复制到该层并进行修改。 这样可以将I / O和每个后续层的大小最小化。