1 引言

容器就相当于一个简易的操作系统,我们在上面部署我们的环境,不可避免地产生一些数据,但是,可能由于断电等等原因,容器退出了,那么之前容器中的数据就不符存在,则往往不是我们想要的,更多的,我们是希望数据能够持久保存到硬盘中,这就需要用到数据卷。

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

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

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

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

2 数据卷

2.1 通过命令添加数据卷

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

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

主义,命令中使用的路径最好使用绝对路径,否则可能会报错。另外,有的时候,可能会省略宿主机路径,只写容器内的数据卷路径,这时候,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自动创建的。

再次,我们尝试在宿主机中修改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、c1、c2逐级挂载,这是没有问题的,而且,--volumes-from参数所挂载的数据卷的容器并不需要保持运行状态,也即是说dbContainer、c1、c2任意一个容器退出也不会影响其他两个容器。

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

 
 
 
 
 

docker系列(四):数据卷的更多相关文章

  1. Docker系列八: 数据卷

    什么是数据卷 生成环境中使用docker的过程中,往往需要对数据进行持久化,或者需要多个容器之间进行数据共享,这个就涉及到了容器数据管理 容器中管理数据主要有两种方式: 数据卷:容器内数据之间映射到本 ...

  2. docker学习5--docker数据卷(volume)

    https://blog.csdn.net/dream_broken/article/details/52314993 1.什么是数据卷volume 为了了解什么是Docker Volume,首先我们 ...

  3. Docker容器的数据卷(data volume),数据卷容器,数据卷的备份和还原。

    Docker容器的数据卷(data volume),数据卷容器,数据卷的备份和还原. 数据卷就是数据(一个文件或者文件夹). Docker的理念之一是将应用与其运行的环境打包,docker容器的生命周 ...

  4. Docker提交镜像-数据卷-可视化

    在熟悉完Docker的安装及基本命令使用之后,我们开始学习下Docker的进阶操作:包括但不限于新建Docker镜像,数据卷的挂载,以及Docker的可视化等. Docker提交镜像 启动镜像 我们先 ...

  5. Docker 使用指南 (四)—— 数据卷的使用

    一.数据卷的使用 有时候需要使用数据库,但是又希望它的数据能保存在本地,Docker中提供了数据卷可以供你方便的操作数据.数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用 ...

  6. Docker容器的数据卷

    一.数据卷概念 1.数据卷是宿主机中的一个目录或文件 2.当容器目录和数据卷目录绑定后,对方的修改会立即同步 3.一个数据卷可以被多个容器同时挂载 4.一个容器也可以挂载多个数据卷 简单理解:有点类似 ...

  7. 使用docker inspect获取数据卷信息时返回地址为空

    使用 docker inspect 命令查看容器挂载的volume的目录 $ sudo docker inspect --format "{{.Volumes}}" redis-m ...

  8. 【Docker】利用数据卷容器来备份、恢复、迁移数据卷

    利用数据卷容器来备份.恢复.迁移数据卷 可以利用数据卷对其中的数据进行进行备份.恢复和迁移. 备份 首先使用 --volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从主机挂载 ...

  9. docker仓库及数据卷

    docker help rmi, 删除本地镜像 docker run -it --name=centos centos:latest /bin/sh  --name的选项可以方便我们以后引用此imag ...

  10. Docker 容器的数据卷

    数据卷的特点: 1. 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中 2. 数据卷可以在容器之间共享和重用 3. 可以对数据卷里的内容直接进行修改 ...

随机推荐

  1. SSM框架之Spring(5)JdbcTemplate及spring事务控制

    Spring(5)JdbcTemplate及spring事务控制 ##1.JdbcTmeplate 它是 spring 框架中提供的一个对象,是对原始 Jdbc API 对象的简单封装.spring ...

  2. javascript模块化开发(二)

    模块化开发(一) ES6模块化 详解 ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict". 顶层的this指向undefined,即不应该在顶层代码 ...

  3. JavaScript学习笔记-----NaN、isNan

    NaN  /  Number.NaN 全局属性 NaN 的值表示不是一个数字(Not-A-Number), NaN 属性的初始值就是 NaN,和 Number.NaN 的值一样. 在现代浏览器中(ES ...

  4. View和ViewGroup

    1.继承关系 2.组合关系 3.View 的绘制流程 3.1.创建R.attrs.styleable,申明需要用到的属性值,在使用时可以根据属性进行定义   3.2.extends View  ,依次 ...

  5. Hadoop、storm和Spark Streaming简单介绍(非原创)

    文章大纲 一.Hadoop是什么二.storm是什么三.Spark Streaming是什么四.Spark与storm比较五.参考文章   一.Hadoop是什么 1. 简介 Hadoop是一个由Ap ...

  6. python连数据库制作音乐软件

    import pymysql conn = pymysql.connect(host="localhost",user="root",password=&quo ...

  7. mysql 安装(Linux、Ubuntu)

    1.检查系统是否已经安装过mysql rpm -qa | grep mysql 若出现类似于以上的结果则表明系统已经安装过mysql,执行以下命令卸载 rpm -e --nodeps mysql-co ...

  8. Linux开发环境搭建三 使用mount -t cifs 挂载windows共享目录方法与问题解决

    转载链接:https://blog.csdn.net/fuyuande/article/details/82915800 嵌入式开发通常是在linux环境下编译,windows下开发,这就需要在lin ...

  9. 如何在mysql数据库生成百万条数据来测试页面加载速度

    1.首先复制一条sql 在复制前,需要确定该记录是否有主键 若无,则代码非常简单, "; 复制的表名↑                                   粘贴的表名↑    ...

  10. centos 6.9 升级glibc动态库

    glibc是gnu发布的libc库,即c运行库,glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc.glibc除了封装linux操作系统所提供的系统服务外,它本身也提供 ...