回顾一下上一章节,在运行私有库时,我们使用了-v参数,将Registry仓库的目录从容器内部挂载到外部宿主机,方便联调。这里其实就是使用了容器卷挂载的机制。
# 一、容器卷概念
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性。卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷。
一句话:有点类似我们Redis里面的rdb和aof文件。
将docker容器内的数据保存进宿主机的磁盘中,运行一个带有容器卷存储功能的容器实例。
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
# 二、容器卷作用
将运行的环境打包成镜像,run后形成容器实例运行 ,但是我们对数据的要求希望是持久化的。
Docker容器产生的数据,如果不备份,那么当容器实例删除后,容器内的数据自然也就没有了。为了能保存数据在docker中我们使用卷。
特点:
(1)数据卷可在容器之间共享或重用数据
(2)卷中的更改可以直接实时生效
(3)数据卷中的更改不会包含在镜像的更新中
(4)数据卷的生命周期一直持续到没有容器使用它为止
# 三、卷挂载问题解决
Docker挂载主机目录访问如果出现cannot open directory : Permission denied问题,需要我们在执行挂载时,后面加一个--privileged=true
CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,在SELinux里面挂载目录被禁止掉了,如果要开启,我们一般使用--privileged=true
命令,扩大容器的权限解决挂载目录没有权限的问题,使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。
那么权限的扩大使用是否会带来安全问题,答案是会的,因为这意味着进程拥有了比普通进程更多的权限。这样做可能会增加系统遭受恶意攻击的风险,因为进程可能会执行危险的操作,或者被黑客用来获取系统权限。关于容器安全的问题,我们后面再进行研究。
# 四、数据卷挂载实操
# 1、映射添加容器卷
# 直接通过一条命令实现
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录 镜像名
# 例如下面这条命令
docker run -it --name myu3 --privileged=true -v /tmp/myHostData:/tmp/myDockerData ubuntu /bin/bash
2
3
4
来看一下ChatGPT对上述命令的解析: 上述命令是在Docker中运行一个名为"myu3"的容器,并为该容器设置了一些参数和选项。让我对每个部分进行解释:
docker run
: 这是Docker命令的一部分,用于创建并运行一个新的容器。-it
: 这是两个选项的组合,-i
表示交互式运行,-t
表示分配一个终端(tty)。这将允许您与容器进行交互,并在终端中执行命令。--name
myu3: 这是给容器指定一个名称的选项。在这种情况下,容器的名称被设置为"myu3"。--privileged=true
: 这是一个选项,将容器设置为具有特权权限。通过设置为"true",容器将获得比普通容器更高的权限,可以执行一些特权操作。但请注意,这样的权限可能会带来安全风险。-v /tmp/myHostData:/tmp/myDockerData
: 这是将主机系统上的目录/tmp/myHostData
映射到容器内的目录/tmp/myDockerData
的选项。这样做可以实现主机和容器之间的文件共享。左侧是主机目录,右侧是容器内的目录。ubuntu
: 这是要在容器中运行的镜像名称。在这种情况下,它是Ubuntu的官方镜像。/bin/bash
: 这是要在容器中运行的命令。在这种情况下,它是启动一个交互式Bash shell。
综上所述,该命令将创建并运行一个名为"myu3"的容器,具有特权权限,并且主机的/tmp/myHostData
目录将与容器内的/tmp/myDockerData
目录进行文件共享。您可以通过交互式Bash shell与容器进行交互并执行命令。
可以使用命令docker inspect 容器ID
查看容器数据卷是否挂载成功
此时容器和宿主机之间实现数据共享,docker中修改,主机同步获得结果,主机中修改,docker同步获得结果,当docker容器stop,主机中修改,再启动docker容器查看数据仍然会同步。
# 2、读写规则映射添加
默认情况下是可读可写的,使用docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:rw 镜像名
指定rw(rw = read + write)和不指定时效果是相同的。
当然我们也可以设置为数据卷只读,这样再容器实例内部就会被限制,只能读不能写。
docker run -it --privileged=true -v /宿主机绝对路径目录:/容器内目录:ro 镜像名
/容器目录:ro 镜像名
,就能完成功能,此时容器自己只能读取不能写。ro(ro = read only) 此时如果宿主机写入内容,可以同步给容器内,容器可以读取到。
# 3、卷的继承和共享
我们使用两个容器来完成这一步操作,首先容器1完成和宿主机的映射。
docker run -it --privileged=true -v /mydocker/u:/tmp --name u1 ubuntu
让容器2继承容器1的卷规则。
docker run -it --privileged=true --volumes-from 父类 --name u2 ubuntu
这里的父类是指要继承哪个容器的卷规则,我们上一步将容器1命名为u1,那么这里的父类名就要写u1。
可以看到,u2的/tmp目录下会有刚才u1创建的文件,并且u2也能够在这个卷内写入自己的内容。