这篇文章主要讲解了“Docker目录挂载及文件共享的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Docker目录挂载及文件共享的方法”吧!Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷(Data Volume)。数据卷可以用来存储Docker应用的数据,也可以用来在Docker容器间进行数据共享。数据卷呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用Docker的数据卷,类似在系统中使用 mount 挂载一个文件系统。想要了解Docker Volume,首先我们需要知道Docker的文件系统是如何工作的。Docker镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上(镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docke免费云主机域名r容器,并通过该镜像重新启动时,之前的更改将会丢失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。
为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念。简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。
最常用的其实就是目录挂载和文件共享的使用。Docker容器启动的时候,如果要挂载宿主机的一个目录,可以用-v参数指定,这个其实也是创建一个数据卷,只不过是把一个本地主机的目录当做数据卷挂载在容器上。
譬如我要启动一个 CentOS 容器,宿主机的 /hostTest 目录挂载到容器的 /conainterTest 目录,可通过以下方式指定:
这样在容器启动后,容器内会自动创建 /conainterTest 的目录。通过这种方式,我们可以明确一点,即-v参数中,冒号”:”前面的目录是宿主机目录,后面的目录是容器内目录。下面我们来验证一下: 我服务器上的docker 版本都是18.09.2
首先执行命令:
run 一个 centos 的镜像,如果本地没有的话,会去执行docker pull centos下载,并生成一个 centos-demo-1 的容器,并进入交互模式
这时候就可以看到容器里面已经有生成/conainterTest这个目录了,接下来我们在这个目录下创建了一个 123 的文件,然后退出容器。
回到宿主机之后,可以看到宿主机对应的目录已经有/hostTest这个目录了,并且也有 123 这个文件。
而且我们还再新建了一个 456 文件,看看会不会同步到容器中,接下来启动容器查看一下:
可以看到这个是有的,所以这两个目录其实就是共享的。接下来具体分析一下这个命令的几种情况。具体指令如下:
直接报错,提示 conainterTest 不是一个绝对路径,所谓的绝对路径,必须以下斜线“/”开头。先把宿主机的目录删掉:然后在run容器:
ps: 因为有为容器命名,但是因为相同名字的容器创建会报错,所以这边我有一个隐形操作,就是每次操作,都会先执行:
当然这个不是重点,所以后面我不会再把这个操作再说明,默认每次run的时候,如果名字相同,那么我就会先删掉同名的容器。
查看宿主机,发现新增了/hostTest这个目录
这次,我们换个目录名 hostTest1 试试:
接下来去 / 查找有没有增加 hostTest1 目录:
发现找不到?? 那么 hostTest1 在哪里创建呢? 通过docker inspect命令,查看容器“Mounts”那一部分,我们可以得到这个问题的答案。
可以看出,容器内的 /conainterTest 目录挂载的是宿主机上的 /var/lib/docker/volumes/hostTest1/_data 目录。
原来,所谓的相对路径指的是/var/lib/docker/volumes/,与宿主机的当前目录无关。先启动一个容器:
发现 /test2 在容器中有存在,那么宿主机的目录在哪里呢?? 用docker inspect查看一下:
可以看出,同上例中的结果类似,只不过,它不是相对路径的目录名,而是随机生成的一个目录名。首先开启一个容器,并查看容器内 /conainterTest/ 的属性
接下来查看宿主机内 /hostTest 目录的属性:
可以看到都是 root。接下来我们在容器内新建用户,修改 /conainterTest 的属主和属组:
可以看到已经将属主和属组都变成 kbz 了。接下来查看宿主机 /hostTest 的属主和属组是否会改变??
发现改变了,但是并不是 kbz,而是一个 privoxy ??
原来,这个与UID有关系,UID,即“用户标识号”,是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。首先查看容器内victor对应的UID是多少:
kbz 的 UID 为 1000,那么宿主机内 1000 对应的用户是谁呢?
果然是 privoxy, 那么就说的通了。在这里,主要验证两种情况:指定了宿主机目录,即 -v /hostTest:/conainterTest。没有指定宿主机目录,即 -v /conainterTest首先的第一种情况:
我们先把宿主机的 hostTest 目录删掉,然后进行挂载,再把容器删掉,最后发现挂载时候建的 hostTest 还存在。
可以看出,即便容器销毁了,新建的挂载目录不会消失。进一步也可验证,如果宿主机目录的属主和属组发生了变化,容器销毁后,宿主机目录的属主和属组不会恢复到挂载之前的状态。第二种情况:
通过上面的验证知道,如果没有指定宿主机的目录,则容器会在 /var/lib/docker/volumes/ 随机配置一个目录,那么我们看看这种情况下的容器销毁是否会导致相应目录的删除:
首先启动容器:
然后通过 docker inspect 来查看挂载的宿主机的目录:
对应的是/var/lib/docker/volumes/22…83/_data目录, 去查看一下这个目录是否存在:
发现该目录依然存在。而且即使重启了docker服务,该目录依旧存在。可通过两种方式解决:关闭selinux。
临时关闭:# setenforce 0
永久关闭:修改/etc/sysconfig/selinux文件,将SELINUX的值设置为disabled。以特权方式启动容器
指定–privileged参数挂载的路径权限默认为读写。如果指定为只读可以用:ro
这时候,如果在容器的挂载目录下进行读写操作的话,就会报错。不仅可以挂载目录,还可以挂载文件。如果挂载目录可以理解为系统的目录映射的话,那么挂载文件,也可以理解为文件映射。
语法跟挂载目录差不多。不过有一点要注意的是,挂载宿主机文件的时候,该文件一定要存在,如果该文件不存在,就会跟上面例子说的一样,docker会自动帮你创建,但是这时候它创建的时候,就是目录了,而不是文件了。
接下来尝试一下:
我创建了一个 web.list 的文件,并且写入了两行,这时候就开始挂载这个文件了:
可以看到挂载成功了,并且在容器内又在 web.list 写入新的一行,并退出容器
可以看到在宿主机,之前容器新写的一行也同步过来了,而且之后宿主机也新加了一行,之后进入容器也一样有。
挂载文件跟上述挂载目录一样,也是默认为读写的,如果设置为只读的话,那么在容器里面就不能修改了,只能在宿主机修改:
可以看到在容器内编辑是会报错的,而在宿主机内就不会。上述的挂载目录和挂载文件,只是 Docker Volume 的使用方式。
而我们用的方式就是在docker run命令后面跟上-v参数即可创建一个数据卷,然后把本地目录或者文件当做数据卷挂载到容器中。当然也可以跟多个-v参数来创建多个数据卷。
因此我们完全可以创建一个数据卷的容器,后面专门用来提供其他容器来挂载。
首先先创建一个专门用来提供数据的本地目录,然后挂载到一个普通的容器,而这个容器就是其他容器要挂载的数据卷容器,这种方式主要就是用来做多个容器的共享数据存在的。
go-data 这个目录存放一些 golang 语言的项目,然后我们把它做成一个数据卷容器,并指向容器的 /go/src 目录:
这样这个就生成了一个名为 centos-go-data 的数据卷容器了,容器里面 /go/src 目录含有一个叫做 goworker 的 go 程序。刚好我服务器上之前有一个 go-1.10 环境的镜像。
接下来我们将这个镜像 run 起来,并且挂载 centos-go-data 这个数据卷容器(通过 –volumes-from 可以挂载数据卷容器),看看原来 /go/src 里面应该为空的目录,会不会有这个数据卷容器里面的go程序代码?
可以看到原本应该有空的 src 目录,竟然有代码目录存在了,说明这个数据卷挂载成功了。接下来将这个 goworker 添加一个文件,看会不会同步到挂载的那个本地目录:
发现本地目录也出现刚才在容器中出现的 123 文件了,说明还是共享成功了。 这时候我们再 run 一个新的 golang 环境的容器,然后也挂载这个数据卷看看数据会不会也有这个 123 文件?
发现新的容器也有这个 123 文件。
其实很多时候这种数据卷容器都是用来做持久化的,举个例子,比如我有一些golang的测试代码,做成了一个数据卷容器,然后我本地有好几个不同go环境的容器,每一个容器在 run 的时候,都会挂载这个数据卷容器。但是我们不希望在go环境的容器里面去修改这个
这篇文章主要介绍了Javascript如何将数组中的所有值相加,具有一定借鉴价值,感兴趣的朋友可以参考免费云主机域名下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。reduce()方法接收一个函数作为累加器,数组中的每个值(从左到右)开…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。