防踩坑:出现Docker挂载主机目录访问出现cannot open directory.: Permission denied…
解决办法:在挂载目录后多加一个--privileged=true
参数即可。
出现上面问题的原因是:通常情况下Linux系统会把不安全的项禁止掉,目录挂载的操作默认情况下被看作是不安全的行为。即在SELinux里面挂载目录被禁止掉了,如果要开启,我们通常需要使用--privileged=true
命令,来扩大容器的权限解决挂载目录没有权限的问题。其实上面这个过程可以理解为:将容器内部的root
拥有本地主机的root
权限,不然容器内部的root
只是外部的一个普通用户。
卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统(也就是说独立于Docker运行的,对卷的各种操作并不会影响Docker本身结构内容)。因此,卷的设计目的就是实现数据的持久化,完全独立于容器的生命周期,因此Docker不会在容器删除时,删除挂载的数据卷。
通过容器数据卷的方式,Docker容器数据通过与外部硬盘、阿里云盘、本地文件夹等外部存储的互联,以实现容器数据的持久化、关键数据的备份等功能。
直白地说,有点类似于Redis中的rdb
和aof
文件,将Docker容器内的数据保存到宿主机的磁盘中,即运行一个带有容器卷存储功能的容器实例。这样就能实现了宿主机某个文件夹与容器内部某个文件的映射,完成两者连通,实现数据的共享与存储。
总的来说:
(1)数据卷可以在数据之间共享和数据重用;
(2)数据卷的更改可以实时生效;
(3)数据卷中的更改不会包含在镜像的更新中;
(4)数据卷的生命周期一直持续到没有容器使用它为止。
1. 命令格式
实现容器卷与主机连接的代码格式如下所示:
docker run -it --previleged=true -v /宿主机绝对路径目录:/容器内目录 镜像名或镜像ID:版本号
代码中的参数含义如下所示:
-it
:以交互式的方式打开镜像为容器;-v
:容器卷绑定;/宿主机绝对路径目录
为本地的文件夹,/容器内目录
是容器内的目录;镜像名或镜像ID
:需要打开的镜像。具体展示一个实例:
docker run -it --privileged=true -v /liang/My_Container_bp:/tmp/docker_data --name='ubuntu16.04' ubuntu:16.04
上面代码的镜像名字,可以由下图确定。对于建立容器卷映射的文件名称映射时,系统会自动创建文件夹。
执行完上面的指令后,在容器内部就有了/tmp/docker_data
文件夹了:
在本地电脑中就存在/liang/My_Container_bp
文件夹了,Docker容器卷与主机连接完成。如果我们在这两个文件中创建各种文件时候,两者都会同步数据。
如果想查看有关更细节的信息,可以使用如下指令:
docker inspect 容器ID或容器名
总的来说,Docker容器卷与主机连接主要实现的内容为:
(1)Docker修改,主机同步获得;
(2)主机修改,docker同步获得;
(3)Docker容器stop,主机修改,Docker与主机数据仍然同步。
通常在添加容器与主机互联时候,主机对容器内部的数据默认是可读/可写的:
docker run -it --privileged=true -v /liang/My_Container_bp:/tmp/docker_data:rw --name='ubuntu16.04' ubuntu:16.04
如上面所示,在-v
参数后面的文件映射的:rw
,表示主机对容器是可读/可写的。
但是有的时候,我们需要实现容器实例ubuntu16.04-read_only
内部只能读不能写,这个时候就需要添加关键字:ro
,代码如下所示:
docker run -it --privileged=true -v /liang/My_Container_bp_ro:/tmp/docker_data:ro --name='ubuntu16.04-read_only' ubuntu:16.04
执行完上面内容,我们进入容器ubuntu16.04-read_only
,如果在/tmp/docker_data
目录下创建一个文件read_only_file.txt
,则显示该文件不能创建,因为/tmp/docker_data
目录是一个只读文件系统。这样做的好处是:防止多个用户在使用容器的时候随意修改主机中的内容,有效的保护了主机数据。
而当我们在主机的/liang/My_Container_bp_ro
目录下创建文件时候,则能正常创建,并且与容器内部/tmp/docker_data
目录共享文件数据:
因此,我们看出
ro
参数只是限制容器的写权限,而不限制主机的读写权限。
这里我们分两个步骤,介绍Docker容器卷之间的继承:
1 容器1与宿主机的映射:
为了方便演示,我们在主机的/liang
目录下创建一个文件夹Container_Inherent
,然后在该目录下创建一个容器文件夹:Container1
:
然后创建Docker容器1的容器卷/tmp/Container1
与主机文件夹/liang/Container_Inherent/Container1
的连接,代码如下所示:
docker run -it --privileged=true -v /liang/Container_Inherent/Container1:/tmp/Container1 --name='Container1' ubuntu:16.04
实现容器2继承容器1的卷规则的代码格式如下:
docker run -it --privileged=true --volumes-from 父类 --name='Container2' 镜像名字或容器ID:版本号
实现容器2继承容器1的卷规则的具体的代码如下所示:
docker run -it --privileged=true --volumes-from Container1 --name='Container2' ubuntu:16.04
这样,我们就创建了一个Container2,它继承了Container1的容器卷/tmp/Container1
与主机文件夹/liang/Container_Inherent/Container1
的数据共享了。为了演示,我们进入Container2容器,进入/tmp
文件夹,可以发现已经有了文件夹Container1
,在这个文件夹下创建一个文件Share_between_Container1_and_Host.txt
:
这时候,我们发现容器Container1和主机目录liang/Container_Inherent/Container1
中也同时创建了Share_between_Container1_and_Host.txt
文件。因此,容器2继承容器1的卷规则完成。