docker系列(四):数据卷
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 ../
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命令中添加-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系列(四):数据卷的更多相关文章
- Docker系列八: 数据卷
什么是数据卷 生成环境中使用docker的过程中,往往需要对数据进行持久化,或者需要多个容器之间进行数据共享,这个就涉及到了容器数据管理 容器中管理数据主要有两种方式: 数据卷:容器内数据之间映射到本 ...
- docker学习5--docker数据卷(volume)
https://blog.csdn.net/dream_broken/article/details/52314993 1.什么是数据卷volume 为了了解什么是Docker Volume,首先我们 ...
- Docker容器的数据卷(data volume),数据卷容器,数据卷的备份和还原。
Docker容器的数据卷(data volume),数据卷容器,数据卷的备份和还原. 数据卷就是数据(一个文件或者文件夹). Docker的理念之一是将应用与其运行的环境打包,docker容器的生命周 ...
- Docker提交镜像-数据卷-可视化
在熟悉完Docker的安装及基本命令使用之后,我们开始学习下Docker的进阶操作:包括但不限于新建Docker镜像,数据卷的挂载,以及Docker的可视化等. Docker提交镜像 启动镜像 我们先 ...
- Docker 使用指南 (四)—— 数据卷的使用
一.数据卷的使用 有时候需要使用数据库,但是又希望它的数据能保存在本地,Docker中提供了数据卷可以供你方便的操作数据.数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用 ...
- Docker容器的数据卷
一.数据卷概念 1.数据卷是宿主机中的一个目录或文件 2.当容器目录和数据卷目录绑定后,对方的修改会立即同步 3.一个数据卷可以被多个容器同时挂载 4.一个容器也可以挂载多个数据卷 简单理解:有点类似 ...
- 使用docker inspect获取数据卷信息时返回地址为空
使用 docker inspect 命令查看容器挂载的volume的目录 $ sudo docker inspect --format "{{.Volumes}}" redis-m ...
- 【Docker】利用数据卷容器来备份、恢复、迁移数据卷
利用数据卷容器来备份.恢复.迁移数据卷 可以利用数据卷对其中的数据进行进行备份.恢复和迁移. 备份 首先使用 --volumes-from 标记来创建一个加载 dbdata 容器卷的容器,并从主机挂载 ...
- docker仓库及数据卷
docker help rmi, 删除本地镜像 docker run -it --name=centos centos:latest /bin/sh --name的选项可以方便我们以后引用此imag ...
- Docker 容器的数据卷
数据卷的特点: 1. 数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中 2. 数据卷可以在容器之间共享和重用 3. 可以对数据卷里的内容直接进行修改 ...
随机推荐
- Easyui 去除jquery-easui tab页div自带滚动条
去除jquery-easui tab页div自带滚动条 by:授客 QQ:1033553122 测试环境 jquery-easyui-1.5.3 需求场景 打开tab页面时,自动载入一个iframe页 ...
- Burpsuite抓取https数据包
Burpsuite抓取https包 浏览器代理设置 Burpsuite代理设置 启动Burpsuite,浏览器访问127.0.0.1:8080,点击CA Certificate,下载cacert.de ...
- could not launch process: debugserver or lldb-server not found: install XCode's command line tools or lldb-server
0x00 事件 VS 调试 go 的时候,发生了这个错误,导致无法调试: could not launch process: debugserver or lldb-server not found: ...
- 43-安装 Docker Machine
前面我们的实验环境中只有一个 docker host,所有的容器都是运行在这一个 host 上的.但在真正的环境中会有多个 host,容器在这些 host 中启动.运行.停止和销毁,相关容器会通过网络 ...
- SQL高效运行注意事项(四)
为了SQLSERVER能高效运行,SQLSERVER的磁盘子系统是一个重要的方面 Avg. Disk Sec/Read 这个计数器是指每秒从磁盘读取数据的平均值 下面的列表显示这个计数器值的范围,并指 ...
- 初级模拟电路:3-10 BJT实现开关电路
回到目录 1. 基本用法 用BJT晶体管实现开关功能是经常会用到的实用电路.和逻辑门电路类似,当BJT用于开关电路时,也只工作于饱和区和截止区. 开关功能的实现电路如下图所示,负载可以是发光二极管.电 ...
- [PHP] cli环境下php设置进程名字
if (function_exists('cli_set_process_title')) { cli_set_process_title("superman php master proc ...
- Bert镜像制作及flask生产环境模式启动
一天搞定两大技术点,成就满满. 一,dockerfile FROM harbor.xxx.com.cn/3rd_part/tensorflow:1.14.0-gpu-py3-jupyter LABEL ...
- .NET Core 3.1 Preview 1 发布
今天,我们正式发布 .NET Core 3.1 Preview 1..NET Core 3.1将是一个小版本,着重于Blazor和Windows桌面开发的功能改进,同时这也是.NET Core 3.0 ...
- python做中学(二)bool()函数的用法
定义: bool() 函数用于将给定参数转换为布尔类型,如果没有参数,返回 False. bool 是 int 的子类. 语法: 以下是 bool() 方法的语法: class bool([x] 参数 ...