一、将Docker数据挂载到容器

在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即***数据不随着Container的结束而结束***),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:

(1)volumes:Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式

由上图可以知道,目前所有Container的数据都保存在了这个目录下边,由于没有在创建时指定卷,所以Docker帮我们默认创建许多匿名(就上面这一堆很长ID的名字)卷。

(2)bind mounts:意为着可以存储在宿主机系统的任意位置;(比较常用的方式

但是,bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。

(3)tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统;(一般都不会用的方式

三种方式的示意图如下所示:

二、Volume的基本使用

管理卷

# docker volume create edc-nginx-vol // 创建一个自定义容器卷
# docker volume ls // 查看所有容器卷
# docker volume inspect edc-nginx-vol // 查看指定容器卷详情信息

volume也是绕过container的文件系统,直接将数据写到host机器上,只是volume是被docker管理的,docker下所有的volume都在host机器上的指定目录下/var/lib/docker/volumes。

将my-volume挂载到container中的/mydata目录:

docker run -it -v my-volume:/mydata alpine sh

然后可以查看到给my-volume的volume:

docker volume inspect my-volume
[{"CreatedAt": "2018-03-28T14:52:49Z","Driver": "local","Labels": null,"Mountpoint": "/var/lib/docker/volumes/my-volume/_data","Name": "my-volume","Options": {},"Scope": "local"}
]

可以看到,volume在host机器的目录为/var/lib/docker/volumes/my-volume/_data。此时,如果my-volume不存在,那么docker会自动创建my-volume,然后再挂载。

也可以不指定host上的volume:

docker run -it -v /mydata alpine sh

此时docker将自动创建一个匿名的volume,并将其挂载到container中的/mydata目录。匿名volume在host机器上的目录路径类似于:/var/lib/docker/volumes/300c2264cd0acfe862507eedf156eb61c197720f69e7e9a053c87c2182b2e7d8/_data

除了让docker帮我们自动创建volume,我们也可以自行创建:

docker volume create my-volume-2

然后将这个已有的my-volume-2挂载到container中:

docker run -it -v my-volume-2:/mydata alpine sh

需要注意的是,与bind mount不同的是,如果volume是空的而container中的目录有内容,那么docker会将container目录中的内容拷贝到volume中,但是如果volume中已经有内容,则会将container中的目录覆盖。请参考这里。

Dockerfile中的VOLUME

在Dockerfile中,我们也可以使用VOLUME指令来申明contaienr中的某个目录需要映射到某个volume:

#Dockerfile
VOLUME /foo

这表示,在docker运行时,docker会创建一个匿名的volume,并将此volume绑定到container的/foo目录中,如果container的/foo目录下已经有内容,则会将内容拷贝的volume中。也即,Dockerfile中的VOLUME /foodocker run -v /foo alpine的效果一样。

Dockerfile中的VOLUME使每次运行一个新的container时,都会为其自动创建一个匿名的volume,如果需要在不同container之间共享数据,那么我们依然需要通过docker run -it -v my-volume:/foo的方式将/foo中数据存放于指定的my-volume中。

因此,VOLUME /foo在某些时候会产生歧义,如果不了解的话将导致问题。

Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定。

譬如我要启动一个CentOS容器,宿主机的/test目录挂载到容器的/soft目录,可通过以下方式指定:

# docker run -it -v /test:/soft centos /bin/bash

这样在容器启动后,容器内会自动创建/soft的目录。通过这种方式,我们可以明确一点,即-v参数中,冒号":"前面的目录是宿主机目录,后面的目录是容器内目录。

貌似简单,其实不然,下面我们来验证一下:

常见问题

一、容器目录不可以为相对路径

[root@localhost ~]# docker run -it -v /test:soft centos /bin/bash invalid value "/test:soft" for flag -v: soft is not an absolute path See 'docker run --help'.

直接报错,提示soft不是一个绝对路径,所谓的绝对路径,必须以下斜线“/”开头。

二、宿主机目录如果不存在,则会自动生成

如果宿主机中存在/test目录,首先删除它

[root@localhost ~]# rm -rf /test [root@localhost ~]# ls / bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

启动容器

[root@localhost ~]# docker run -it -v /test:/soft centos /bin/bash [root@a487a3ca7997 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin soft srv sys tmp usr var

查看宿主机,发现新增了一个/test目录

[root@localhost ~]# ls / bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var

三、宿主机的目录如果为相对路径呢?

这次,我们换个目录名test1试试

# docker run -it -v test1:/soft centos /bin/bash

再到宿主机上查看是否新增了一个/test1目录,结果没有,是不是因为我用的是相对路径,所以生成的test1目录在当前目录下,结果发现还是没有。那容器内的/soft目录挂载到哪里去了?通过docker inspect命令,查看容器“Mounts”那一部分,我们可以得到这个问题的答案。

"Mounts":[{"Name":"test1","Source":"/var/lib/docker/volumes/test1/_data","Destination":"/soft","Driver":"local","Mode":"z","RW":true}]

可以看出,容器内的/soft目录挂载的是宿主机上的/var/lib/docker/volumes/test1/_data目录

原来,所谓的相对路径指的是/var/lib/docker/volumes/,与宿主机的当前目录无关。

四、如果只是-v指定一个目录,这个又是如何对应呢?

启动一个容器

[root@localhost ~]# docker run -it -v /test2 centos /bin/bash [root@ea24067bc902 /]# ls bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys test2 tmp usr var

同样使用docker inspect命令查看宿主机的挂载目录

"Mounts":[{"Name":"96256232eb74edb139d652746f0fe426e57fbacdf73376963e3acdb411b3d73a","Source":"/var/lib/docker/volumes/96256232eb74edb139d652746f0fe426e57fbacdf73376963e3acdb411b3d73a/_data","Destination":"/test2","Driver":"local","Mode":"","RW":true}]

可以看出,同3中的结果类似,只不过,它不是相对路径的目录名,而是随机生成的一个目录名。

五、如果在容器内修改了目录的属主和属组,那么对应的挂载点是否会修改呢?

首先开启一个容器,查看容器内/soft目录的属性

[root@localhost ~]# docker run -it -v /test:/soft centos /bin/bash [root@b5ed8216401f /]# ll -d /soft/ drwxr-xr-x 2 root root 6 Sep 24 03:48 /soft/

查看宿主机内/test目录的属性

[root@localhost ~]# ll -d /test/ drwxr-xr-x 2 root root 6 Sep 24 11:48 /test/

在容器内新建用户,修改/soft的属主和属组

[root@b5ed8216401f /]# useradd victor [root@b5ed8216401f /]# chown -R victor.victor /soft/
[root@b5ed8216401f /]# ll -d /soft/ drwxr-xr-x 2 victor victor 6 Sep 24 03:48 /soft/

再来看看宿主机内/test目录的属主和属组是否会发生变化?

[root@localhost ~]# ll -d /test/ drwxr-xr-x 2 mycat mycat 6 Sep 24 11:48 /test/

竟然变为mycat了。。。

原来,这个与UID有关系,UID,即“用户标识号”,是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。

首先查看容器内victor对应的UID是多少,

[root@b5ed8216401f /]# cat /etc/passwd | grep victor victor:x:1000:1000::/home/victor:/bin/bash

victor的UID为1000,那么宿主机内1000对应的用户是谁呢?

[root@localhost ~]# cat /etc/passwd |grep 1000 mycat:x:1000:1000::/home/mycat:/bin/bash

可以看出,宿主机内UID 1000对应的用户是mycat。

六、容器销毁了,在宿主机上新建的挂载目录是否会消失?

在这里,主要验证两种情况:

一、指定了宿主机目录,即 -v /test:/soft。
二、没有指定宿主机目录,即-v /soft

第一种情况:

[root@localhost ~]# rm -rf /test  --首先删除宿主机的/test目录 [root@localhost ~]# ls /  --可以看到,宿主机上无/test目录
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@localhost ~]# docker run -it --name=centos_test -v /test:/soft centos /bin/bash --启动容器,为了删除方便,我用--name参数指定了容器的名字 [root@82ad7f3a779a /]# exit exit
[root@localhost ~]# docker rm centos_test --删除容器 centos_test [root@localhost ~]# ls / --发现 /test目录依旧存在
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys test tmp usr var

可以看出,即便容器销毁了,新建的挂载目录不会消失。进一步也可验证,如果宿主机目录的属主和属组发生了变化,容器销毁后,宿主机目录的属主和属组不会恢复到挂载之前的状态。

第二种情况,通过上面的验证知道,如果没有指定宿主机的目录,则容器会在/var/lib/docker/volumes/随机配置一个目录,那么我们看看这种情况下的容器销毁是否会导致相应目录的删除

首先启动容器

[root@localhost ~]# docker run -it --name=centos_test -v /soft centos /bin/bash [root@6b75579ec934 /]# exit exit

通过docker inspect命令查看容器在宿主机上生成的挂载目录

"Mounts":[{"Name":"b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301","Source":"/var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301/_data","Destination":"/soft","Driver":"local","Mode":"","RW":true}]

对应的是/var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301/_data目录

销毁容器,看目录是否存在

[root@localhost ~]# docker rm centos_test centos_test
[root@localhost ~]# ll /var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301 total 0 drwxr-xr-x 2 root root 6 Sep 24 14:25 _data

发现该目录依旧存在,即便重启了docker服务,该目录依旧存在

[root@localhost ~]# systemctl restart docker
[root@localhost ~]# ll /var/lib/docker/volumes/b53164cb1c9f1917788638692fb22ad11994cf1fbbc2461b6c390cd3e10ea301 total 0 drwxr-xr-x 2 root root 6 Sep 24 14:25 _data

七、挂载宿主机已存在目录后,在容器内对其进行操作,报“Permission denied”。

可通过两种方式解决:

  • 1> 关闭selinux。

临时关闭:# setenforce 0

永久关闭:修改/etc/sysconfig/selinux文件,将SELINUX的值设置为disabled。

  • 2> 以特权方式启动容器

指定–privileged参数

如:# docker run -it --privileged -v /test:/soft centos /bin/bash

Docker(五):Docker Volume相关推荐

  1. Docker | Docker技术基础梳理(五) - Docker网络管理

    Docker | Docker技术基础梳理(五) - Docker网络管理 链接: 原文链接 原文链接: https://gitbook.cn/books/5b8f3c471966b44b00d265 ...

  2. Docker系列 五.Docker容器数据卷

    五.Docker容器数据卷 环境&工具: 阿里云轻量级服务器.CentOS 7系统.FinalShell(其他连接客户端也可以) 是什么 docker的理念将运行的环境打包形成容器运行,运行可 ...

  3. Docker系列(二十三)——Docker实例五Docker安装MongoDB实例

    < Docker实例三Docker安装MongoDB实例 > 前言 在前面一篇文章种,完成了 < Docker安装MySQL实例 >,本篇将继续镜像安装教程,并完成Docker ...

  4. GPS定位系统(五)——Docker

    前言 前面已经把Android.Java.web端都弄得差不多了,现在,需要打包并进行服务器部署了,这样,我们的网站也能够在公网上给大家进行访问.接下来,想要学习一下docker来进行服务器环境的搭建 ...

  5. 解决 Windows Docker 安装 Gitlab Volume 权限问题

    解决 Windows Docker 安装 Gitlab Volume 权限问题 参考文章: (1)解决 Windows Docker 安装 Gitlab Volume 权限问题 (2)https:// ...

  6. Docker系列五~docker安装php-fpm

    Docker系列五 docker安装php-fpm 访问PHP镜像库地址: https://hub.docker.com/_/php?tab=tags 选择合适的版本 php-fpm镜像主要是提供ph ...

  7. Docker Networking Data Volume

    Overlay Network 叠加网络 Docker Network Docker 安装完成后有三种网络 bridge host none ~]#docker network ls NETWORK ...

  8. docker mysql volum_docker volume 使用

    docker volume 可以理解成一个container中的磁盘,既可以跟随container的生命周期(在Dockerfile 中定义使用VOLUME关键字),也可以单独创建,永久存储,直到用d ...

  9. docker mysql volum_Docker Volume入门用法详解

    Docker Volume能让容器从宿主主机中读取文件或持久化数据到宿主主机内,让容器与容器产生的数据分离开来.你可以简单地把它理解为linux服务器上的挂载点.一个容器可以挂载多个不同的目录.Vol ...

  10. docker mysql volum_Docker Volume

    什么是数据卷Volume呢? 首先需要明确Docker内的文件系统是如何工作的,Docker镜像被存储在一系列的只读层. Docker镜像是由多个文件系统(只读层)叠加而成,当启动一个容器的时候,Do ...

最新文章

  1. Android listview 的应用
  2. 在spring中使用自定义注解注册监听器
  3. [ASP.NET MVC2 系列] ASP.NET MVC 之如何创建自定义路由约束
  4. 用CSS让DIV上下左右居中的方法
  5. 1024,节日快乐!
  6. 我构建应用的这十年......
  7. 怎样提高学生计算机应用能力,能力学生论文,关于如何提高技校生计算机的应用能力相关参考文献资料-免费论文范文...
  8. ArrayList(1.8)
  9. 将参数传递给Bash函数
  10. Windows 下 Git 的安装及如何与码云协作
  11. python气象数据处理与绘图(9)_《利用Python进行数据分析·第2版》第9章 绘图和可视化...
  12. 传智播客-刘意-java深入浅出精华版学习笔记Day07
  13. JAVA调用海康威视SDK
  14. 安装VMware时勾选增强型键盘驱动程序有什么用?
  15. 计算机基础知识刷题app,计算机考试刷题app
  16. 计算机被覆盖文件怎么恢复,如何找回被覆盖的文件?恢复被覆盖文件的方法
  17. 电脑的Windows图片查看器找不到怎么办
  18. 密码学中Alice(爱丽丝)和鲍勃(Bob)的历史
  19. 比例阀为什么需要比例阀放大器
  20. Qt中Q_D和Q_P的作用

热门文章

  1. R函数:交集intersect、并集union、找不同setdiff、判断相同setequal
  2. Nature综述:真菌的多样性:真菌的高通量测序及鉴定
  3. Nature Method:HUMAnN2实现宏基因组和宏转录组种水平功能组成分析
  4. Nature :全球表层土壤中微生物组的结构和功能
  5. html接收model数据,QAbstractTableModel数据返回要显示的html代码
  6. R语言数据包自带数据集之ISwR包的melanom数据集字段解释、数据导入实战
  7. R语言使用pwr包的pwr.t.test函数对分组样本数相同的t检验进行效用分析(power analysis)、在已知效应量(effect size)、显著性水平、效用值的情况下计算需要的样本量
  8. Python偏相关(Partial Correlation)或者部分相关性系数计算实战:偏相关性(Partial Correlation)计算及结果解读
  9. R语言dplyr包对数据进行超前或者之后处理(lead、lag)实战
  10. python使用imbalanced-learn的SMOTEENN方法同时进行上采样和下采样处理数据不平衡问题