分层结构
当容器启动时,一个新的可写层被加载到镜像的顶部。
这一层通常被称作“容器层”,“容器层”之下的都叫
“镜像层”。所有对容器的改动 - 无论添加、删除、还
是修改文件都只会发生在容器层中。只有容器层是可写
的,容器层下面的所有镜像层都是只读的.镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。
OverlayFS
OverlayFS是一个现代联合文件系统,实现更快,更简单。
Docker为OverlayFS提供了存储驱动程序 --overlay和overlay2
通过docker info 命令可以看到当前系统使用的存储驱动为
容器的读写
对于读,考虑下列3种场景:
读的文件不在容器层:如果读的文件不在容器层,则从镜像层进行读
读的文件只存在在容器层:直接从容器层读
读的文件在容器层和镜像层:读容器层中的文件,因为容器层隐藏了镜像层同名的文件(上层覆盖底层)
对于写,考虑下列场景:
写的文件不在容器层,在镜像层:由于文件不在容器层,因此overlay/overlay2存储驱动使用copy_up操作从镜像层拷
贝文件到容器层,然后将写入的内容写入到文件新的拷贝中。
删除文件和目录:删除镜像层的文件,会在容器层创建一个whiteout文件来隐藏它;删除镜像层的目录,会创建
opaque目录,它和whiteout文件有相同的效果
通过对容器的读写操作,来举例说明
将修改后的容器提交为镜像
将现有容器生成新的镜像,
docker命令为:docker commit -m ”提交信息” 容器ID 镜像名称:tag名称。
生成的镜像如上图
通过docker inspect 命令查看新镜像信息,在之前的镜像上增加了一层镜像
修改dockerfile文件查看镜像
1、只修改了最后一步,所以镜像依赖基本不变,只是顶层镜像文件改变 echo “mmm” > mm.txt
2、而当中间插入一步时(mkdir /data2),只有最底层的镜像文件没变,后面的都变掉了,因为后面的依赖的文件改变了,其实相同的命令产生的镜像,diff中的文件还是相同的
数据卷-VOLUME
Docker中的数据可以存储在类似于虚拟机磁盘的介质中,称为数据卷(Data Volume)。
数据卷可以用来存储Docker应用的数据,也可以用来在Docker容器间进行数据共享。数据卷呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用Docker的数据卷,类似在系统中使用 mount 挂载一个文件系统
创建数据卷,三种方式:
1、在dockerfile中通过VOLUME指令来增加一个或者多个数据卷
2、docker run命令后面跟上-v参数即可创建一个数据卷,当然也可以跟多个-v参数来创 建多个数据卷
3、docker volume create volume_name 命令先创建一个数据卷
1、通过dockerfile创建数据卷 VOLUME[“/data1”,”/data2”]
生成的数据卷保存在 /var/lib/docker/volumes目录下
镜像生成不会是数据卷生成
只有容器启动时才会生成数据卷(docker run –it –name=“volume1” 镜像ID)
2、docker run –it –v /data3 –name=“volume2” 镜像ID
相对于1来说,会生成新的数据卷
以上两种方式的数据卷名称是系统默认名称
3、创建好数据卷之后
可以指定数据卷名称挂载容器目录 – docker run –it –v volume_name:/data4 –name=“volume4” 镜像ID
当创建好带有数据卷的容器后,就可以在其他容器中通过--volumes-froms参数来挂载该数据卷了,不管该容器是否运行。
停止上面新创的容器(docker ps –a|grep 容器名称 来查看容器状态)
挂载前一容器的数据卷 – docker run –it –volumes-from 容器ID --name=“volume3” 镜像ID
与前一容器的数据卷路径相同 – docker inspect 查看
容器间实现了数据共享 -- 修改volume3中的数据,volume2中出现了同样的数据
即使删除了刚开始的第一个数据卷容器,只要有其他容器使用数据卷,数据卷都不会被删除的
删除创建数据卷的容器 -- volume2
volume3中数据卷并没有被删除,因为还有容器挂载在该数据卷中
删除volume3容器,/var/lib/docker/volumes中的数据卷也不会删除,只是没有办法被容器所引用,因为挂载它的容器都被删除了。
查看所有数据卷 docker volume ls
删除需要用docker volume rm 卷名,如果还有容器挂载了该数据卷,那么删除会报错
也可以把一个本地主机的目录当做数据卷挂载在容器上,同样是在docker run后面跟-v参数,不过-v后面跟的不再是单独的目录了,它是[host-dir]:[container-dir]:[rw|ro]这样格式的,host-dir是一个绝对路径的地址。
运行一个容器,以读写方式挂载宿主机上的/data1/www/fjh目录–-
docker run –it --name=“volume5”–v /data1/www/fjh:/data/fjh(:rw 默认) 镜像ID
查看启动的容器中获得了宿主机的目录,并向其中添加文件
数据与宿主机之间进行了共享
查看数据卷中并没有生成新的文件夹,说明不是生成docker的数据卷,而是将宿主机上的目录当成了数据卷
当删除容器后,修改保留在了宿主机上
当运行一个容器时,挂载了宿主机上一个不存在的目录时,容器和宿主机同时回新增这个目录,并将容器的内容同步进宿主机
如果host-dir存在,但是指向的是一个不存在的目录,则docker也会创建该目录,然后使用该目录做数据源。
如果host-dir不存在,则docker会创建一个新的数据卷,
如果 host-dir和docker中的目录都存在,则宿主机上的目录会把docker中的目录给覆盖
备份数据卷的内容的方法可以是创建一个新容器,挂载数据卷容器,同时挂载一个本地目录,然后把数据卷容器的数据卷通过备份命令备份到映射的本地目录里面。
将容器volume2挂载的数据卷的数据内容同步到宿主机 --
docker run –rm –volumes-from=volume2 –name=“volume8” -v /data/www/fjh3:/fjh3:rw 镜像ID cp –rf /data1 /fjh3
启动一个新的容器并且从volume2容器中挂载卷,然后挂载主机/data1/www/fjh3目录到容器中的/fjh3目录,并将数据卷中的/data1 目录中的数据拷贝到/fjh3中,那么数据卷中的内容就同步到宿主机中去了,并且执行完之后把该容器删除。
Docker Volume数据卷的优点:
1)绕过“拷贝写”系统,会直接改变宿主机上的数据卷中的内容,且有些文件不需要在docker commit打包进镜像文件。
2)数据卷可以在容器间共享和重用数据
3)数据卷可以在宿主和容器间共享数据
4)数据卷是持续性的,直到没有容器使用它们。