一、VOLUME指令说明
Docker镜像被存储在一系列的只读层。当我们开启一个容器,Docker读取只读镜像并添加一个读写层在顶部。如果正在运行的容器修改了现有的文件,该文件将被拷贝出底层的只读层到最顶层的读写层。在读写层中的旧版本文件隐藏于该文件之下,但并没有被不破坏 - 它仍然存在于镜像以下。当Docker的容器被删除,然后重新启动镜像时,将开启一个没有任何更改的新的容器 - 这些更改会丢失。此只读层及在顶部的读写层的组合被Docker称为Union File System(联合文件系统)。
为了能够保存(持久)数据以及共享容器间的数据,Docker提出了Volumes的概念。
Volume可以将容器以及容器产生的数据分离开来,这样,当你使用docker rm container删除容器时,不会影响相关的数据;
Volume可以使得多个容器共享数据;
即我们可以在宿主机上创建一个目录与容器的某个目录(称为挂载点、或者叫卷)关联起来,容器上的挂载点下的内容就是宿主机的这个目录下的内容。
二、VOLUME使用方式
1.通过docker run命令创建挂载点
首先,查看本地的镜像:
我们tomcat:7这个镜像来启动容器并且创建挂载点:
说明:
docker run是启动容器命令; -d代表后台运行; -P代表端口自动帮我们绑定; --name tomcat代表将启动的容器命名为tomcat; -v标记在容器中设置了一个挂载点 /usr/local/data(就是容器中的一个目录),并将主机上的 /home/env/containerdata 目录中的内容关联到/usr/local/data下。
容器启动后,先查看宿主机/home/env目录下是否有一个containerdata:
宿主机已存在该目录,接着我们进入容器内部,查看是否生成/usr/local/data目录:
不管宿主机或容器内部,都自动创建了目录,接着我们在宿主机创建一个abc文件,再来查看下容器内是否同步了abc文件:
最后,我们在容器内部创建hello文件,看宿主机挂载的目录是否也存在hello文件:
注意:在启动容器时设置挂载点也可以不指定宿主机的目录,这时docker会自动绑定主机上的一个目录:
通过docker inspect 容器命令可以查看到挂载的目录:
上面 Mounts下的每条信息记录了容器上一个挂载点的信息,"Destination" 值是容器的挂载点,"Source"值是对应的主机目录,查看宿主机是否存在该目录:
注意:使用docker run命令的-v标识创建的挂载点只能对创建的容器有效,如果要创建多个容器,那么每个容器创建时必须指定挂载点。
2.通过dockerfile创建挂载点
通过dockerfile的 VOLUME 指令可以在镜像中创建挂载点,这样只要通过该镜像创建的容器都有了挂载点,但值得注意的是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,而是自动生成的
首先,编写dockerfile:
#base image FROM centos #MAINTAINER,this dockerfile creater MAINTAINER loose@docker.com #VOLUME,指定挂在目录 VOLUME ["/usr/local/data1"]
其次,通过该dockerfile构建镜像:
最后,启动容器,再通过docker inspect查看挂在到宿主机的目录:
启动容器
根据容器查看挂在信息
注意:在dockerfile中VOLUME可以指定多个挂在目录,即["/usr/local/data1","/usr/local/data2"]代表这两个目录都会挂在到宿主机的自动生成的目录。
3.容器共享挂载点(共享卷)
启动容器时使用--volumes-from 被共享的容器来共享挂载点
首先,创建两个dockerfile,我们要分来源于同一个镜像和来源于不同镜像共享挂载点:
第一个dockerfile:
#base image FROM tomcat:7 #MAINTAINER,this dockerfile creater MAINTAINER loose@docker.com #VOLUME指令,配置挂载目录参数 VOLUME ["/usr/local/volume1","/usr/local/volume2"]
第二个dockerfile:
#base image FROM tomcat:7 #MAINTAINER,this dockerfile creater MAINTAINER loose@docker.com #VOLUME指令,配置挂载目录参数 VOLUME ["/usr/local/volume3"]
其次,我们分别根据这两个dockerfile构建两个镜像,分别是tomcat1,tomcat2:
接着,查看我们的镜像:
在准备工作做好后,我们先根据tomcat:v1.0创建一个容器出来,然后校验是否挂载成功:
①.启动容器
②.进入容器中,根据docker inspect 容器查看自动挂载到宿主机的目录
容器中,已经根据dockerfile VOLUME参数生成了两个目录
③.接下来查看挂载到宿主机的目录
④.来源于同一个镜像的不同容器间的挂载目录共享
由于我们目前的容器tomcat1是通过镜像dae47854feea启动的,所以我们重新启动个容器,依然是通过镜像dae47854feea启动,来达到同一个镜像中的不同容器间挂载目录的共享
命令:
docker run --name tomcatextend -it --volumes-from tomcat1 dae47854feea /bin/bash
查看新容器tomcatextend:
通过docker inspect 容器查看该容器共享的挂载目录:
再去对比下tomcat1这个容器的挂载目录,完全一致,证明已经共享挂载目录了。
⑤.来源于不同镜像的不同容器间的挂载目录共享
再次查看本地镜像,方便看整个流程:
目前,仅有的两个容器都是基于tomcat1:v1.0这个镜像生成的容器,所以这次我们根据tomcat2:v1.0镜像启动的容器,并且指定共享的挂载目录来源于镜像为tomcat:v1.0的tomcat1容器,以达到不同镜像的不同容器间的挂载目录共享
说明:tomcat3共享了tomcat1的挂载目录就拥有volume1和volume2两个共享目录,再加tomcat3本身是通过tomcat2:v1.0启动,而tomcat2:v1.0通过dockerfile构建时本身就自带挂载目录volume3,所以这里展示出来是3个。
以上就是分不同情况共享挂载目录。
上面的命令总结:
#指定挂在目录
docker run --name tomcat -it -v /home/env/containerdata:/usr/local/data image /bin/bash
#docker会自动绑定主机上的一个目录 docker run --name tomcat -it -v /usr/local/data image /bin/bash
#自动绑定主机上的目录,需要查看主机目录路径,通过docker inspect 容器可查看
#共享挂载点 1.来源同一个镜像 docker run --name tomcatextend -it --volumes-from tomcat1 dae47854feea /bin/bash #这里的image是启动tomcatextend和tomcat1容器是的同一个镜像 2.来源不同镜像 docker run --name tomcat2 -it --volumes-from tomcat1 86ba8c26af60 /bin/bash
#这里的tomcat2是通过86ba8c26af60镜像启动,而tomcat1是通过镜像dae47854feea启动