Docker进阶之容器数据卷(Volume)

一、什么是数据卷?什么是容器数据卷?

       数据卷就是一个文件或者文件夹。

       Docker的理念之一是将应用与其运行的环境打包,docker容器的生命周期是与其运行的程序一致的,而对数据的要求是持久化,docker容器之间也需要有共享数据的渠道。

       数据卷是特殊的目录,可以绕过联合文件系统,为一个或多个容器提供访问。数据卷设计的目的是数据的持久化,数据卷的生命周期完全独立于容器,不会在容器删除时删除其挂载的数据卷,也不会存在类似垃圾收集机制,对容器引用的数据卷进行处理。

       数据卷存在于宿主机中,独立于容器,和容器的生命周期是分离的,数据卷存在于宿主机的文件系统中,数据卷可以是目录也可以是文件,容器可以利用数据卷与宿主机进行数据共享,实现了容器间的数据共享和交换。

       通俗地来说,docker容器数据卷可以看成使我们生活中常用的u盘,它存在于一个或多个的容器中,由docker挂载到容器,但不属于联合文件系统,Docker不会在容器删除时删除其挂载的数据卷。

二、Volume的作用/特点

  • 通过数据卷可以在容器之间实现共享和重用
  • 对数据卷的修改会立马生效(非常适合作为开发环境)
  • 对数据卷的更新,不会影响镜像
  • 卷会一直存在,直到没有容器使用

三、Docker添加数据的两种方式

1、使用命令的方式添加数据卷

在使用docker run的时候我们可以通过 -v 来创建一个数据卷并挂载到容器上,在一次run中多次使用可以挂载多个容器。命令语法:docker run -it -v /宿主机绝对路径:/容器绝对路径 镜像名

打开命令行终端,使用docker命令以交互式的方式来运行centos

[root@localhost /]# docker run --name centos -it -v /home/huangxin/hostdata/:/dataVolmeContainer --privileged=true 67fa590cfc1c /bin/bash 
[root@aa29e3790769 /]# ls
anaconda-post.log  bin  dataVolmeContainer  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@aa29e3790769 /]# cd dataVolmeCOntainer
[root@localhost /]# docker run -it  -v /home/huangxin/hostdata:/dataVolmeContainer centos 
[root@0504f3b67b95 /]# ls      #进入到容器内部,容器内部的目录创建好了
anaconda-post.log  bin  dataVolmeContainer  dev  etc  home  lib  lib64 

如果发现挂载在容器中的目录没有访问权限,可以加上--privileged=true这个参数。启动成功后我们可以用前面我们学过一个命令docker inspect 容器名/容器ID来查看关于一个容器的有关细节,打开我们发现主机和容器之间的共享已经建立起来了,而且默认都是可读可写的:

接下来然容器和主机之间互相共享数据:
在另一个终端中来到/home/huangxin/hostdata目录下,新建text1.txt,然后在里面写点东西:

[huangxin@localhost ~]$ cd /home/huangxin/hostdata
[root@localhost hostdata]# touch text1.txt
[root@localhost hostdata]# ls
text1.txt
[root@localhost hostdata]# vim text1.txt

随便写点东西:

然后来到容器里,就可以看到主机在主机端的共享文件夹中写的数据在容器中可以看到了:

接着我们反向操作看看能不能在容器中写的数据在主机可以共享到。

[root@aa29e3790769 dataVolmeContainer]# touch Demo1.txt
[root@aa29e3790769 dataVolmeContainer]# vi Demo1.txt
[root@aa29e3790769 dataVolmeContainer]# ls
Demo1.txt  text1.txt

还是随便写了点东西在新建的Demo1.text中,然后在主机端去看看有没有。

[root@localhost hostdata]# ls
Demo1.txt  text1.txt
[root@localhost hostdata]# cat Demo1.txt
Here is container!!!Hello Host.

可以看到主机和容器之间可以相互共享文件了;而且对这些文件都具有读写的权限。即使容器停止后,这些共享的数据还是同步的。然而有时我们不需要让容器写数据,那么我们就可以用带权限的命令:docker run -it -v /宿主机绝对路径:/容器绝对路径:ro 镜像名ro表示read only。

四、使用DockerFile添加数据卷

编写自定义的Dockerfile,可以使用VOLUME []命令可以挂载任意多个共享目录,以json的格式,多个目录逗号隔开。

FROM centos
VOLUME ["/data1","/data2"]
CMD echo "finished-----SUCCESS"
CMD /bin/bash

使用docker build命令通过Dockerfile构建一个镜像
docker build的基本语法:docker build [OPTIONS] PATH | URL | -
* -f,--file 指定Dockerfile的路径名
* -t,--tag 指定镜像的REPOSITORY 和标签

常用的写法:docker build -f Dcokerfile的路径 -t 仓库:标签

[root@localhost docker]# docker build -f /home/huangxin/docker/Dockerfile -t xust-hx/centos .
Sending build context to Docker daemon 2.048 kB
Step 1/4 : FROM centos
 ---> 67fa590cfc1c
Step 2/4 : VOLUME /data1 /data2
 ---> Running in 296561fadbc5
 ---> da4cfb9f98d5
Removing intermediate container 296561fadbc5
Step 3/4 : CMD echo "finished-----SUCCESS"
 ---> Running in 668697ef3ba4
 ---> ec2bf3c54a54
Removing intermediate container 668697ef3ba4
Step 4/4 : CMD /bin/bash
 ---> Running in 5b3d43b5114a
 ---> e61c27683817
Removing intermediate container 5b3d43b5114a
Successfully built e61c27683817
[root@localhost docker]# docker images
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
xust-hx/centos            latest              e61c27683817        13 seconds ago      202 MB
xust/tomcat               1.0.0               71a1320815f5        19 hours ago        506 MB

可以看到我们的镜像构建成功了,下来我们来启动基于我们构建镜像的一个容器。

[root@localhost docker]# docker run -it e61c27683817 /bin/bash

使用ls查看,发现容器中自动就挂载了两个文件夹data1,data2

但是这两个文件夹对应在主机上的什么地方呢?
使用docker inspect来看看这个运行中的容器的详细信息

可以看到,docker对于使用VOLUME挂载的共享目录,在主机中会有一个默认的文件夹——"/var/lib/docker/volumes/。在这个文件夹下你有挂载几个,docker就默认给你生成几个对应的共享目录。

[root@localhost huangxin]# cd /var/lib/docker/volumes/402caff5bb629320e524e8239b4ca121be7d11ce4df4b55b657bdcfdc549b543/_data
[root@localhost _data]# pwd
/var/lib/docker/volumes/402caff5bb629320e524e8239b4ca121be7d11ce4df4b55b657bdcfdc549b543/_data
[root@localhost _data]# vim Dem01.txt

还是一样随便在Dem01.txt中写点东西,然后去容器中的data1目录看看有没有Demo1.txt以及内容。

[root@6f062b92cccb /]# cd data1
[root@6f062b92cccb data1]# ls
Demo1.txt
[root@6f062b92cccb data1]# cat Demo1.txt
Hello,this is host of data1!

五、容器之间共享数据

让容器之间共享数据,有一种方法是可以通过数据卷来实现,首先启动一个父容器(启动我们刚才制作的那个镜像)

[root@localhost docker]# docker run -it --name centos01 e61c27683817 
[root@a5c471c5b738 /]# ls
anaconda-post.log  bin  data1  data2  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
//在data1目录下新建centos01.txt
[root@a5c471c5b738 /]# vi centos01.txt

在centos01.txt中随便写点东西,然后在启动子容器时候使用命令参数:--volumes-from来和父容器共享数据,

[root@localhost docker]# docker run -it --name centos02 --volumes-from centos01  e61c27683817 
[root@fec297cd7c00 /]# ls     
anaconda-post.log  bin  data1  data2  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
[root@fec297cd7c00 /]# cd data1
[root@fec297cd7c00 data1]# vim centos02.txt
//在centos02.txt中随便写点东西
//在启动一个子容器
[root@fec297cd7c00 data1]# [root@localhost docker]# docker run -it --name centos03 --volumes-from centos01  e61c27683817 
[root@1a8862870583 /]# cd data1
[root@1a8862870583 data1]# ls
centos01.txt centos02.txt
[root@1a8862870583 data1]# vi centos03.txt

//同样在centos03.txt中随便写点东西

最终达到的效果:父子容器都可以互相共享各自的数据:

那么如果我们删除了父容器,父容器以前共享的数据还在吗?子容器之间的共享还会有吗?
来,一张图回答这个问题:

留言区

还能输入500个字符