Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
若是运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏,这个就是写时复制(COW)机制。docker
Docker 容器数据的存储,存在如下问题:shell
关闭并重启容器,容器的数据不受影响。但删除容器会是以前的更改所有丢失。json
解决方案:卷(volume),或者便于区分叫作存储卷。
卷是容器上的一个或多个目录,此类目录可绕过联合文件系统,与宿主机上的某个目录绑定(关联)。数组
Volume在容器初始化之时就会建立,由base image提供的卷中的数据会于此期间完成复制。网络
Volumn的初衷就是独立于容器的生命周期实现数据持久化,所以删除容器之时既不会删除卷,也不会对哪怕未被引用的卷作垃圾回收操做。ide
卷为docker提供了独立于容器的数据管理机制:3d
如今,在建立容器时,加上volumes的相关选项。code
Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,可是在宿主机上的位置有所不一样:生命周期
为docker run命令使用-v选项,便可使用Volume。内存
开一个会话建立容器并绑定volume:
$ docker run --name v1 --rm -it -v /data busybox
在宿主机上操做目录
在另外一个会话中查询这个容器的inspect,不过内容比较多。在Volumes里能看到卷的信息:
"Volumes": { "/data": {} },
还有挂载点的信息,这里使用-f参数只看Mounts的内容:
$ docker inspect -f '{{json .Mounts}}' v1 [{"Type":"volume","Name":"bdd48fb729e802b7d3a067da74b748037e83ff770a84f7215c657f6cc2af2c9d","Source":"/var/lib/docker/volumes/bdd48fb729e802b7d3a067da74b748037e83ff770a84f7215c657f6cc2af2c9d/_data","Destination":"/data","Driver":"local","Mode":"","RW":true,"Propagation":""}] $
宿主机自动分配的卷的路径在Source字段中,下面的方法直接获取路径并调用ls命令:
$ docker inspect -f '{{range .Mounts}}{{.Source}} {{end}}' v1 | xargs ls $ docker inspect -f '{{with index .Mounts 0}}{{.Source}}{{end}}' v1 | xargs ls
Mounts里是一个数组,可能有多个挂载点。第一行的命令是遍历全部的目录,第二行的命令是只输出第一个目录。
在挂载点的目录中,容器和宿主机能够共享数据。容器中对目录的修改,在宿主机中能够查看到。反之,在宿主机中对这个目录的修改,容器也可以查看到。
删除镜像
上面建立容器的命令使用了--rm参数,这样一旦容器中止,该容器也就会自动被删除。容器删除后,Docker-managed volume也会一并被删除。
因此这是一个临时的卷,卷内存储的数据依然会随着容器的删除而丢失。没有解决容器内数据持久保存的目的,可是如今容器的数据能够和宿主机共享,而且数据存储的I/O也直接是由宿主机的文件系统决定。好处是用户不用额外来管理这个卷,卷内存放的临时数据会随着容器的删除而删除。适合用于存放临时性的可是须要在容器外的共享的数据。
使用的参数仍是和以前同样,可是-v参数的内容提供两部分,宿主机的目录和卷的目录,中间用冒号分隔:-v HOSTDIR:VOLUMEDIR
。
绑定 Bind-mount Volme
开一个会话建立容器并绑定Bind-mount Volme:
$ docker run --name v2 --rm -it -v ~/data/volumes/v2:/data busybox
仍然可使用docker inspect命令来查看详细信息,这里就不演示了。
这里指定的宿主机的路径若是不存在,docker会自动建立。
删除容器
容器删除后,宿主机上的文件会依然存在。这样就实现了数据在容器删除后依然可使用。
前面说了,docker有两种类型的卷,两种都已经说了。这里的共享卷本质上仍是上面两种类型中的某一种,只是是实现了容器间共享同一个卷的两种方法。
多个容器卷使用同一个主机目录
这个没什么问题,主机上同一个目录是容许被多个容器同时使用的。
复制使用其余容器的卷
使用--volumes-from选项:
$ docker run --name v3.0 --rm -itd -v /data busybox e24397fffb44717a7f140010c829ec88f540ed7d95f7c8fb328a35a819becfb0 $ docker run --name v3.1 --rm -itd --volumes-from v3.0 busybox 28543eb6fc13e972a000ab955b9623630ebb9d90c8d3dc37a8b7608f24188926 $ docker container attach v3.0 / # touch /data/test_v3_0 / # exit $ docker container attach v3.1 / # ls /data test_v3_0 / # exit $
这里的示例复制的是Docker-managed volume,对于Bind-mount Volme也是同样的。
共享网络网络也能够共享,即联盟式网络。这里,卷也能够共享。在有些场景下,两个或几个容器有可能须要共享同一个网络而且共享同一个卷。