Docker磁盘挂载技术-数据卷的使用

磁盘挂载技术-数据卷的使用 一、容器和容器内的数据耦合引发的问题
假设使用运行一个mysql镜像,运行成功之后就自动创建了一个运行mysql的容器 。
随着mysql的使用,mysql容器中的数据会越来越多 。
这时候怎么保存和移植这些数据就成了问题 。而且需要升级mysql的时候也势必要删除旧版本的容器 。
但是一旦删除了这个容器,里面的数据和配置也都灰飞烟灭了 。
因此 , 容器和容器内的数据耦合主要会引发以下几个问题:
容器内部的数据不可以复用
容器难以升级维护
二、数据卷的概念和作用
数据卷() 是一个虚拟目录 , 指向宿主机文件系统中的某个目录 。
一旦某个容器完成数据卷挂载 , 对容器的一切操作都会作用在数据卷对应的宿主机目录了 。
我们操作数据卷对应的宿主机目录也相当于操作容器内部的对应目录 。
它们的修改是双向同步的 , 类似于vue中的双向绑定 。
多个容器也可以绑定到相同的数据卷目录上 。
【Docker磁盘挂载技术-数据卷的使用】从而实现容器内数据与容器解耦 。就能够解决上面的问题 。
因为数据和配置在宿主机上也保存着一份,以后不管是别的容器复用 , 还是去修改数据和配置都是非常方便的 。
并且容器删了,数据卷中的内容也是不受影响的 。
数据卷-容器-宿主机之间的关系如下(以Nginx容器为例):
三、数据卷操作命令
数据卷操作的基本语法:
docker volume COMMAND
语法解析:
是固定写法 。
文档中提供的有5个:
2.3 创建数据卷
docker volume create 数据卷名称# 示例:docker volume create html
2.4 查看数据卷创建数据卷
docker volume ls
2.5 查看数据卷详细信息
docker volume inspect 数据卷名称# 示例:docker volume inspect html
可以看到数据卷的详细信息中,有一个 , 中文是挂载点的意思 。
挂载点也就是当前数据卷中的数据在宿主机上的真实存储目录 。
2.6 删除全部未使用的数据卷
docker volume prune 数据卷名称# 示例:docker volume prune html
2.7 删除一个或多个指定的数据卷
docker volume rm数据卷名称# 示例:docker volume rmhtml
四、数据卷挂载
容器挂载数据卷时,数据卷可以存在也可以不存在 。
数据卷不存在的话,会自动去创建数据卷 。
以修改Nginx主页内容为例:
第一步: 创建容器并挂载数据卷到容器内的HTML目录
# 解释部分# \是命令换行符 docker run \# 创建并运行一个容器--name myNginx \# 给容器个名字叫myNginx-v html:/usr/share/nginx/html \ # 把html数据卷挂载到容器内的/usr/share/nginx/html这个目录中-p 80:80 \# 把宿主机的80端口映射到容器内的80端口-d \# 后台运行nginx \;# 需要启动的镜像名称# 可直接复制部分docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
注意:
html数据卷即使不存在 , 也会自动帮你创建
第二步:查看数据卷所在的位置
docker volume inspect html# 查看html数据卷,指向的宿主机中的具体文件夹位置
此时html数据卷的就已经指向宿主机的/var/lib///html/_data目录 。
第三步:在宿主机中进入html数据卷所在位置,并修改HTML内容
# 进入Mountpoint指向的目录cd /var/lib/docker/volumes/html/_data# 修改Nginx主页的index.html文件vi index.html
注意点:五、磁盘挂载
容器不仅仅可以挂载数据卷 , 也可以直接挂载到宿主机目录上 。
直接挂载模式:宿主机目录 —> 容器内目录 。
此时,就不再有中间的数据卷 , 而是容器和宿主机的直接交互 。
磁盘挂载的语法:
# 语法方面其实也就只有-v 参数有区别,其它都是没区别的# 注意:宿主机文件挂载容器内文件的操作,使用数据卷是做不到的-v [宿主机目录]:[容器内目录]-v [宿主机文件]:[容器内文件]
由于上面已经使用了Nginx作为例子,这里就使用MySql作为例子 。
演示使用磁盘挂载MySql的数据保存目录和MySql的配置文件 。
第一步、拉取/加载镜像
docker pull mysql:5.7.25
MySql镜像有几百兆,直接拉取需要一些时间 。
如果本地已经有了MySql镜像 。可以使用如下命令把本地镜像加载到容器中:
# -i 指定要加载进docker的本地镜像名称docker load -i mysql.tar
第二步:准备宿主机中的文件目录
myLocal.cnf# -p 创建多级目录mkdir -p /mysql/data # 创建存放mysql数据的目录mkdir -p /mysql/conf # 创建存放mysql配置文件的目录cd /mysql/conf# 进入/mysql/conf目录touch myLocal.cnf# 创建本地mysql配置文件,这个文件名称可以自定义
第三步:查阅文档去使用MySql 3.1 选择官方镜像文档
3.2 点击官方镜像文档入口
在栏目下,往下拖动,找到How to use this image 。
这里就有如何启动mysql容器的各种介绍 。
关于文档中启动语句的解释:
# --name some-mysql给容器个名字叫some-mysql# -d让容器后台运行# -emysql环境变量的设置# -e MYSQL_ROOT_PASSWORD=my-secret-p mysql的登录密码为my-secret-pwdocker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
但是其实上面的只是基础的启动命令 。
还缺了端口映射和磁盘挂载部分需要用户自己去写 。
# 解释部分docker run \# 创建并运行一个容器--name mysql \# 给容器个名字叫mysql-e MYSQL_ROOT_PASSWORD=root \# 设置mysql登录,密码为root-p 3306:3306# 把宿主机3306端口和容器的3306端口相关联-v /mysql/conf/myLocal.cnf:/etc/mysql/conf.d \ # 宿主myLocal.cnf文件挂载到容器conf.d文件-v /mysql/data:/var/lib/musql \# 宿主data目录挂载到容器mysql目录-d \# 后台运行mysql:5.7.25# 需要启动的镜像名称# 可直接复制部分docker run \--name mysql \-e MYSQL_ROOT_PASSWORD=root \-p 3306:3306 \-v /mysql/conf/myLocal.cnf:/etc/mysql/conf.d \-v /mysql/data:/var/lib/musql \-d \mysql:5.7.25
3.3 在中找到如何挂载配置文件:
第二个红框处的-v明确了挂载配置文件的写法 。
但是为什么不直接挂载f?
主要是因为文档说f这个文件包含了/etc/mysql/conf.d和/etc/mysql/mysql.conf.d两个目录 。
.d后缀就是代表目录的意思 。
总体文档就是说,/etc/mysql/conf.d和/etc/mysql/mysql.conf.d两个目录里的所有配置会加载到f这个文件中作为最终的MySql配置来使用 。
因此官方的默认配置我们就无需去管,只要把我们自己的配置挂载到/etc/mysql/conf.d目录上 。
最终和官方默认配置合并即可 。这也是官方的推荐做法!
如何挂载数据存储目录可以在Where to Store Data下找到:
这里明确说明,镜像中MySql的数据存储目录为/var/lib/mysql 。
注意点:
挂载主机目录访问如果出现:
cannot open directory .: Permission denied
解决办法:在挂载目录后多加如下参数即可:
--privileged=true
使用该参数 , 内的root拥有真正的root权限.
否则,内的root只是外部的一个普通用户权限 。
六、数据卷中rw和ro读写规则
但执行如下命令时:
docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx
其实就相当于执行了:
docker run --name mn -v html:/usr/share/nginx/html:rw -p 80:80 -d nginx
这说明数据卷和读写规则映射添加说明是rw,也就是读写(默认)的意思 。
这以为着容器对数据卷挂载的目录可以读取也可以写入 。
如果想要容器实例内部被限制,只能对数据卷挂载的容器内部目录读取而不能写入,可以这么做:
docker run --name mn -v html:/usr/share/nginx/html:ro -p 80:80 -d nginx
小结:
rw:容器内部对数据挂载的容器内部的目录具有读写权限
ro:容器内部对数据挂载的容器内部的目录只具有读权限
七、数据卷之间的继承
比如此时运行了一个容器:
docker run -it --privileged=true -v /mydocker/ubuntu:/tmp --name myUbuntu ubuntu
可以看到,容器以磁盘挂载的方式,挂载了一个宿主机目录 。
此时,如果又有一个容器是可以选择继承容器的卷的挂载规则的 。
示例如下:
docker run -it --privileged=true --volumes-from myUbuntu --name myUbuntu2 ubuntu
这样一来容器就继承了容器的卷的挂载规则 。
容器的卷的挂载规则容器就统统都有了 。
八、数据挂载和磁盘挂载的优缺点 6.1 数据挂载方式
使用数据卷挂载的方式,会自动在宿主机上帮我们创建数据卷对应的真实目录 。
容器挂载时只需要挂载到数据卷上,而不用关心数据卷指向的真实目录在哪里 。
即使将来容器被删除了,数据卷中或者宿主机挂载到容器的目录中的内容是不会随着容器的删除而丢失的 。
优点:这种方式相当于把挂载全部交给本身处理,方便快捷 。
缺点:真实挂载目录由生成,目录较深 , 不方便查找 。
6.2 磁盘挂载方式
优点:目录和文件更好找也更好维护 , 并且能直接把目录或者文件挂载到容器上 。
缺点:目录和文件需要我们自行创建和维护 。
6.3 小结
如何选用挂载方式 , 结合实际情况即可 。