docker系列(四):数据卷

1 引言

容器就至关于一个简易的操做系统,咱们在上面部署咱们的环境,不可避免地产生一些数据,可是,可能因为断电等等缘由,容器退出了,那么以前容器中的数据就不符存在,则每每不是咱们想要的,更多的,咱们是但愿数据可以持久保存到硬盘中,这就须要用到数据卷。docker

数据卷是指一种目录或者说文件,其存在于一个或者多个容器中,由docker挂载到容器,但不属于UFS(Union File System,联合文件系统),所以可以绕开UFS提供一些用于持续存储或共享数据的特性。ubuntu

数据卷的设计目的就是为了实现数据的持久化,彻底独立于容器的生存周期,所以docker不会在容器删除时删除其挂载的数据卷。除此之外,数据卷还能够实现容器间的数据继承和共享。在使用上,数据卷的特色:bash

 

  • 数据卷能够在容器之间共享或者重用数据
  • 数据卷中的更改能够直接生效
  • 数据卷中的更改不会包含在镜像的更新中
  • 数据卷的生命周期一直持续到没有容器使用它为止

 

下面就开始来研究一下添加数据卷。添加数据卷有两种方法,第一种是经过命令直接添加,第二种是经过dockerfile添加。ide

2 数据卷

2.1 经过命令添加数据卷

在上一篇博文中,提到过docker run命令,docker run命令中有一个参数-v就是用来添加数据卷的,也就是说,在docker run命令中使用-v参数,能够在启动容器时,为容器添加一个数据卷。命令格式以下:ui

docker run -it -v /宿主机绝对路径目录:/容器内绝对 镜像名spa

主义,命令中使用的路径最好使用绝对路径,不然可能会报错。另外,有的时候,可能会省略宿主机路径,只写容器内的数据卷路径,这时候,docker会在/var/lib/docker/volumes/目录下自行建立一个目录最为主机数据卷目录。操作系统

例如将宿主机的当前用户目录下名为suzu的目录,与容器内根目录下名为rongqi的目录进行映射做为数据卷。命令行

$ docker run -it -v ~/suzhu:/rongqi ubuntu

root@fd4af8e0b8b3:/#

启动容器后,咱们查看一下容器内是否有容器这一目录:设计

root@fd4af8e0b8b3:/# ll rongqi
total 8
drwxr-xr-x 2 root root 4096 Jun 15 02:36 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:36 ../
发现存在rongqi目录。继续,咱们在容器内建立一个名为123的文件,看看宿主机内是否会同步这一文件:
root@fd4af8e0b8b3:/# cd rongqi
root@fd4af8e0b8b3:/rongqi# touch 123
root@fd4af8e0b8b3:/rongqi# ll
total 8
drwxr-xr-x 2 root root 4096 Jun 15 02:40 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:40 ../
-rw-r--r-- 1 root root 0 Jun 15 02:40 123
在宿主机启动另外一个终端,查看是否同步:
$ cd ~/suzhu
~/suzhu$ ll
total 8
drwxr-xr-x 2 root root 4096 Jun 15 10:40 ./
drwxr-xr-x 16 chb chb 4096 Jun 15 10:41 ../
-rw-r--r-- 1 root root 0 Jun 15 10:40 123

看到了没,宿主机rongqi目录中也同步出现了123文件。并且,不管是宿主机的容器目录仍是容器内的rongqi目录都是由docker自动建立的。code

再次,咱们尝试在宿主机中修改123文件的内容,看容器内的123文件是否会修改,注意必定要使用超级管理员权限进行写入才行,这时候主机只有只读权限。以下图所示:

保存后退出,再次回到容器内查看123文件内容:

root@fd4af8e0b8b3:/rongqi# tac 123
我是宿主机,我写入了一行

证实宿主机与容器的同步是双向的。

若是容器中止了,宿主机添加文件,是否会在容器从新启动后同步到呢?

咱们先中止容器,而后在宿主机suzhu目录下建立一个111.txt文件:

root@fd4af8e0b8b3:/rongqi# exit
exit
$ cd ~/suzhu
$ touch 111.txt
$ sudo touch 111.txt

启动刚刚的容器,看看是否出现111.txt文件:

$ docker start fd4af8e0b8b3
fd4af8e0b8b3
$ docker attach fd4af8e0b8b3
root@fd4af8e0b8b3:/# cd rongqi
root@fd4af8e0b8b3:/rongqi# ll
total 12
drwxr-xr-x 2 root root 4096 Jun 15 03:07 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:40 ../
-rw-r--r-- 1 root root 0 Jun 15 03:07 111.txt
-rw-r--r-- 1 root root 37 Jun 15 02:55 123

看到了吗?在容器重启后,在rongqi目录下也出现了111.txt文件。

一个容器能够有多个数据卷吗?

答案是能够的。须要指定多个-v参数来实现。

$ docker run -it -v ~/suzhu:/rongqi -v ~/suzhu2:/rongqi2 ubuntu

继续研究,一个目录能够挂载多个数据卷吗?

$ docker run -it -v ~/suzhu:/rongqi ubuntu
root@deb66cd44a57:/#

容器建立成功。咱们继续尝试使用新建的容器,看看容器间的数据卷内文件是否会同步:

root@deb66cd44a57:/# cd rongqi
root@deb66cd44a57:/rongqi# ll
total 12
drwxr-xr-x 2 root root 4096 Jun 15 03:07 ./
drwxr-xr-x 1 root root 4096 Jun 15 03:40 ../
-rw-r--r-- 1 root root 0 Jun 15 03:07 111.txt
-rw-r--r-- 1 root root 37 Jun 15 02:55 123
root@deb66cd44a57:/rongqi# touch 222.txt

去最初建立的容器中查看:

$ docker attach fd4af8e0b8b3
root@fd4af8e0b8b3:/rongqi# ll
total 12
drwxr-xr-x 2 root root 4096 Jun 15 03:43 ./
drwxr-xr-x 1 root root 4096 Jun 15 02:40 ../
-rw-r--r-- 1 root root 0 Jun 15 03:07 111.txt
-rw-r--r-- 1 root root 37 Jun 15 02:55 123
-rw-r--r-- 1 root root 0 Jun 15 03:43 222.txt

文件同步了。证实一个目录能够被多个容器挂在为数据卷,从而实现容器间的数据同步和共享。

既然一个目录能够被多个容器挂在为数据卷,就须要涉及权限的问题了,例若有的容器须要有读和写的权限,可是,有的容器,只须要有读不能由写入权限,这该怎么办呢?其实只须要挂在目录后面加入权限参数就行了,参数中,rw表示有读和写权限,ro表示只有du的权限,在默认状况下,是rw就同时具备读写权限。咱们继续建立一个容器,对suzhu目录只有只读权限,而后尝试在容器中建立文件:

$ docker run -it -v ~/suzhu:/rongqi:ro ubuntu
root@6df9eaeb444a:/# cd rongqi
root@6df9eaeb444a:/rongqi# touch 333.txt
touch: cannot touch '333.txt': Read-only file system
建立文件失败,由于只有只读的权限。
总结一下在docker run命令中添加数据卷的内容:
  • 在docker run命令中添加-v 宿主机目录:容器目录参数形式进行添加数据卷
  • 若是目录不存在,docker会自动建立
  • 同步是双向的
  • 若是不对权限进行制定,宿主机只有只读权限
  • 容器重启并不影响同步
  • 经过多个-v参数,一个容器挂载多个数据卷
  • 一个目录能够被多个容器挂载,从而实现容器间的数据共享同步。
  • 经过rw和ro参数,能够指定容器对数据卷的读写权限。
  • 指定数据卷目录时,最好使用绝对路径,不要使用相对路径(上面并无演示)

2.2 经过dockerfile添加数据卷

dockerfile内容在前面的博文中已经介绍过了。在dockerfile中有一个专门的命令VOLUME是用来添加数据卷的,VOLUME命令格式以下:

VOLUME ["数据卷目录1", "数据卷目录2"]

注意:数据卷目录1和2都指的是容器内的目录。在docker run中经过-v参数指定宿主机目录:容器目录的方式在dockerfile中是行不通的。这是由于dockerfile是以建立容器的模板做用而存在,可能会应用于不一样的宿主机甚至不一样的系统平台,不一样的平台路径格式也不相同。虽然不能指定宿主机中的目录,不过,经过dockerfile建立爱你的数据卷都默认存在于/var/lib/docker/volumes/目录下。下面咱们使用dockerfile建立数据卷,首先建立一个目录,而后进入该目录,在目录内建立一个名为dockerfile的文件,写入一下内容:

FROM ubuntu
VOLUME ["/dataVolume1","/dataVolume2"]
CMD echo "Success to build volume"
CMD /bin/bash

在命令行下使用docker build命令建立镜像:

$ docker build -t docker_volume .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM ubuntu
---> 7698f282e524
Step 2/4 : VOLUME ["/dataVolume1","/dataVolume2"]
---> Running in 42cee5bb0fc8
Removing intermediate container 42cee5bb0fc8
---> 96e9ce4e0eae
Step 3/4 : CMD echo "Success to build volume"
---> Running in 04fbe86e45cc
Removing intermediate container 04fbe86e45cc
---> f66a3493edc6
Step 4/4 : CMD /bin/bash
---> Running in 6f39c6dbb2d8
Removing intermediate container 6f39c6dbb2d8
---> 42bd7a7b12ff
Successfully built 42bd7a7b12ff
Successfully tagged docker_volume:latest

使用镜像建立容器,而后进入容器查看是否有数据卷:

$ docker run -it 42bd7a7b12ff
root@266fdc2a5ad7:/# ll
total 80
drwxr-xr-x 1 root root 4096 Jun 17 13:26 ./
drwxr-xr-x 1 root root 4096 Jun 17 13:26 ../
-rwxr-xr-x 1 root root 0 Jun 17 13:26 .dockerenv*
drwxr-xr-x 2 root root 4096 May 15 14:07 bin/
drwxr-xr-x 2 root root 4096 Apr 24 2018 boot/
drwxr-xr-x 2 root root 4096 Jun 17 13:26 dataVolume1/
drwxr-xr-x 2 root root 4096 Jun 17 13:26 dataVolume2/

能够看到,dataVolume1和dataVolume2两个目录果真是存在的。

咱们可使用docker inspect命令查看详细信息:

$ docker inspect 266fdc2a5ad7
……
"Mounts": [
{
"Type": "volume",
"Name": "d2d2f7ee61c5f8db0b8ccc2ff08f121079c3f16c5e48cd99e1d65538ef44e389",
"Source": "/var/lib/docker/volumes/d2d2f7ee61c5f8db0b8ccc2ff08f121079c3f16c5e48cd99e1d65538ef44e389/_data",
"Destination": "/dataVolume1",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "eacb8887be7cee176c1901f0e61ab7d51998a11366cc5a4b5fd3313c79f6ba48",
"Source": "/var/lib/docker/volumes/eacb8887be7cee176c1901f0e61ab7d51998a11366cc5a4b5fd3313c79f6ba48/_data",
"Destination": "/dataVolume2",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
]
……

查询出来的信息太多,上面只贴出了数据卷的挂载信息,Name是指数据卷的名称,是自动生成的,Source是宿主机内的数据卷目录,使用超级管理员权限打开/var/lib/docker/volumes/目录能够查看到,Destination是容器内的数据卷目录。

dockerfile建立的数据卷性质与docker run -v命令行建立的是同样的,这里再也不多说。

3 数据卷容器

有时候,咱们有一些常常性发生变化的数据须要在多个容器之间进行共享,这时候,一个更好的选择就是使用数据卷容器。所谓数据卷容器,从名字上也能够看出也是一个容器,不过,这个容器是专门用来为其余容器提供数据卷进行挂在的。

咱们先建立一个带数据卷的容器:

$ docker run -it -v /dbdata --name dbContainer ubuntu

而后用这个容器为其余容器提供数据卷。使用--volumes-from来挂载数据卷容器。以下所示:

~/docker_test$ docker run -it --volumes-from dbContainer --name c1 ubuntu
root@50ce83189ae3:/# ll
total 76
……
drwxr-xr-x 2 root root 4096 Jun 17 14:57 dbdata/
……

能够看到,容器内出现了dbdata目录,这就是经过--volumes-from参数与dbContainer容器挂载而来的。

数据卷容器能够同时被多个容器挂载,甚至,已经挂载了数据卷的容器能够级联挂载别的容器。

$ docker run -it --volumes-from c1 --name c2 ubuntu
root@97e7dae4a04b:/# ll
total 76
……
drwxr-xr-x 2 root root 4096 Jun 17 14:57 dbdata/
……

可见,dbContainer、c一、c2逐级挂载,这是没有问题的,并且,--volumes-from参数所挂载的数据卷的容器并不须要保持运行状态,也便是说dbContainer、c一、c2任意一个容器退出也不会影响其余两个容器。

另外,删除挂载的容器(dbContainer、c一、c2任意一个),数据卷并不会被自动删除,若是要删除数据卷,须要在删除最后一个挂载着这个数据卷的时候显式的使用docker rm -v参数来同时删除容器。

相关文章
相关标签/搜索