问题1
容器是某个软guan件完整的运行环境,包含了一个小型的linux系统。
假设宿主机里面启动了4个一样的nginx容器,一个nginx运行时完整环境有20MB,那么四个nginx合起来占用的磁盘空间是80MB吗?
问题2
在Docker中:
镜像:固定不变的,一个将镜像可以启动很多容器
容器:文件系统中的logs等文件会经常变化
docker在底层使用自己的存储驱动来组织文件内容
镜像如何存储
1、Images and layers
Docker镜像由一系列层组成,每层代表Dockerfile中的一条命令。如下,除了最后一层外的每一层都是只读的
Dockerfile
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD java /app/app.java
- 该Dockerfile有四条命令,每个命令创建一个层
- FROM语句从ubuntu:15.04镜像创建一个图层开始
- COPY命令从Docker客户端的当前目录添加一些文件
- RUN命令使用make命令构建你的应用程序
- 最后一层指定要在容器中运行的命令
- 创建新容器时,可以在基础层之上添加一个新的可写层。 该层通常称为“容器层”。 对运行中 的容器所做的所有更改(例如写入新文件,修改现有文件和删除文件)都将写入此薄可写容 器层。
容器和镜像之间的主要区别是可写顶层。 在容器中添加新数据或修改现有数据的所有写操作都存储在此可写层中。 删除容器后,可写层也会被删除。 基础图像保持不变。 因为每个容器都有其自己的可写容 器层,并且所有更改都存储在该容器层中,所以多个容器可以共享对同一基础映像的访问, 但具有自己的数据状态。
官方Nginx的分层
docker history nginx
nginx镜像是怎么存的 docker image inspect nginx 来查询一下nginx的详情
LowerDir:底层目录
nginx启动命令
/var/lib/docker/fuse-overlayfs/382f0e76d37431fbaf6c318e29758a0808df9984e4e9b9e538d012c5619efda6/diff
nginx启动命令
:/var/lib/docker/fuse-overlayfs/7fa49843d69cc90512737c35a0ed60fe14bae95d3e587098fa61b7d55fe00fe4/diff
nginx启动命令
:/var/lib/docker/fuse-overlayfs/0aabc2419ded49b243fbb92c4ec6d5c438481b95f7bd4d9a725526ebca6f71b2/diff
存放nginx的配置文件
:/var/lib/docker/fuse-overlayfs/4401dd7c3855731e7f2120fbf7d554430269f27c46996c69bbc976f23f864261/diff
小linux系统
:/var/lib/docker/fuse-overlayfs/21359bc683368a66f987dba658c8b0df3cc020d63e8686cc540c91956b78f62d/diff
小linux系统(FROM apline)+ Dockerfile的每一个命令都可能引起系统的修改,Docker和git一样只记录变化
进入小linux系统下,每个文件夹都有一个唯一的ID
我们启动一个以上面nginx为镜像的容器,进入容器相同目录查看文件夹的ID,我们可以看出,相同的文件夹id一样。所以容器的文件系统就是镜像的文件系统 docker ps -s :可以看到容器真正用到的文件大小
MergedDir:合并目录
真正的容器挂载层(容器工作的完整目录)
/var/lib/docker/fuse-overlayfs/3ad3dc5e97990ada4039874b7c481bbd70106ab929f34d662662c08cdba4bf0d/merged
UpperDir:上层目录
/var/lib/docker/fuse-overlayfs/3ad3dc5e97990ada4039874b7c481bbd70106ab929f34d662662c08cdba4bf0d/diff
WorkDir:工作目录
/var/lib/docker/fuse-overlayfs/3ad3dc5e97990ada4039874b7c481bbd70106ab929f34d662662c08cdba4bf0d/work
2、Copy On Write
1、写时复制是一种共享和复制文件的策略,可最大程度的提高效率
2、如果文件或目录位于镜像的较低层中,而另一层(包括可写层)需要对其进行读取访问,则它仅使用现有文件
3、另一层第一次需要修改文件时(在构建镜像或者运行容器时),将文件复制到该层并进行修改。这样可以将I/O和每个后续层的大小最小化。
1、根据上图,现在,我们启动一个nginx容器,此时nginx容器用的是nginx镜像的nginx.conf文件 2、那么,如果我们在容器里修改了nginx.conf文件,此时,会在nginx容器里新增一层保存修改后的nginx.conf,此时,容器再读nginx.conf读的就是我们新加的这一层中的修改过的配置文件
我们来验证一下上面两个结论
1、首先找到镜像里的nginx.conf文件
2、得到镜像里nginx.conf的id是41553509
3、我们再到nginx容器里查看一下nginx.conf的id
4、我们可以看到nginx容器里nginx.conf的id是41553509
5、我们给容器里的nginx增加一点内容发现,id和之前一样,为什么呢?
6、再来看一下容器的详细信息:docker inspect 容器ID
进入以下目录会发现有nginx.conf
UpperDir": "/var/lib/docker/fuse-overlayfs/e6efe3f5b8fc43c3ef244f7b9d1c83f716917896ec8d30d4c480ccf1befee574/diff",
此时,我们可以看到nginx.conf的id发生了变化,并且可以看到我们新增的内容。由此我们可以得出,新增的内容加到了容器的UpperDir层