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

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

一、Docker容器和容器内的数据耦合引发的问题

假设使用Docker运行一个mysql镜像,运行成功之后就自动创建了一个运行mysql的容器。

随着mysql的使用,mysql容器中的数据会越来越多。

这时候怎么保存和移植这些数据就成了问题。而且需要升级mysql的时候也势必要删除旧版本的容器。

但是一旦删除了这个容器,里面的数据和配置也都灰飞烟灭了。

因此,Docker容器和容器内的数据耦合主要会引发以下几个问题:

  • 容器内部的数据和配置难以修改,

    • 想要修改就必须进入容器,还没有vi或者vim可以使用。
    • 修改过后的数据和配置在容器中是没有记录的,久而久之,会难以维护。
  • 容器内部的数据不可以复用

    • 由于容器的隔离机制,容器内的数据和操作对外都是不可见的,对其它新创建的容器没有办法复用已创建容器的数据的。
  • 容器难以升级维护

    • 旧容器升级势必要删除就容器,可是却拿不出旧容器内部的数据和配置。

二、数据卷的概念和作用

数据卷(volume) 是一个虚拟目录,指向宿主机文件系统中的某个目录。

一旦某个容器完成数据卷挂载,对容器的一切操作都会作用在数据卷对应的宿主机目录了。

我们操作数据卷对应的宿主机目录也相当于操作容器内部的对应目录。

它们的修改是双向同步的,类似于vue中的双向绑定。

多个容器也可以绑定到相同的数据卷目录上。

从而实现容器内数据与容器解耦。就能够解决上面的问题。

因为数据和配置在宿主机上也保存着一份,以后不管是别的容器复用,还是去修改数据和配置都是非常方便的。

并且容器删了,数据卷中的内容也是不受影响的。

docker数据卷-容器-宿主机之间的关系如下(以Nginx容器为例):
在这里插入图片描述

三、数据卷操作命令

数据卷操作的基本语法:

docker volume COMMAND

语法解析:

docker volume是固定写法。

文档中提供的COMMAND有5个:

  • create 创建一个数据卷(volume)
  • inspect 显示一个或多个数据卷(volume)的信息
  • ls 列出所有的数据卷(volume)
  • prune 删除全部未使用的数据卷(volume)
  • rm 删除一个或多个指定的数据卷(volume)

2.3 创建数据卷

docker volume create 数据卷名称
# 示例:
docker volume create html

2.4 查看数据卷创建数据卷

docker volume ls

2.5 查看数据卷详细信息

docker volume inspect 数据卷名称
# 示例:
docker volume inspect html

在这里插入图片描述

可以看到数据卷的详细信息中,有一个Mountpoint,中文是挂载点的意思。

挂载点也就是当前数据卷中的数据在宿主机上的真实存储目录。

2.6 删除全部未使用的数据卷

docker volume prune 数据卷名称
# 示例:
docker volume prune html

2.7 删除一个或多个指定的数据卷

docker volume rm  数据卷名称
# 示例:
docker volume rm  html

四、数据卷挂载

容器挂载数据卷时,数据卷可以存在也可以不存在。

数据卷不存在的话,会自动去创建数据卷。

以修改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也会自动帮你创建

第二步:查看数据卷所在的位置

docker volume inspect html			# 查看html数据卷,指向的宿主机中的具体文件夹位置

此时html数据卷的Mountpoint就已经指向宿主机的/var/lib/docker/volumes/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镜像。可以使用如下命令把本地镜像加载到Docker容器中:

# -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配置文件,这个文件名称可以自定义

第三步:查阅DockerHub文档去使用MySql

3.1 选择官方镜像文档

在这里插入图片描述

3.2 点击官方镜像文档入口

Overview栏目下,往下拖动,找到How to use this image

这里就有如何启动mysql容器的各种介绍。
在这里插入图片描述

关于文档中启动语句的解释:

# --name some-mysql    					给容器个名字叫some-mysql
# -d    			   					让容器后台运行
# -e				   					mysql环境变量的设置
# -e MYSQL_ROOT_PASSWORD=my-secret-p	mysql的登录密码为my-secret-pw
docker 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 在DockerHub中找到如何挂载配置文件:

在这里插入图片描述

第二个红框处的-v明确了挂载配置文件的写法。

但是为什么不直接挂载my.cnf?

主要是因为文档说my.cnf这个文件包含了/etc/mysql/conf.d/etc/mysql/mysql.conf.d两个目录。

.d后缀就是代表目录的意思。

总体文档就是说,/etc/mysql/conf.d/etc/mysql/mysql.conf.d两个目录里的所有配置会加载到my.cnf这个文件中作为最终的MySql配置来使用。

因此官方的默认配置我们就无需去管,只要把我们自己的配置挂载到/etc/mysql/conf.d目录上。

最终和官方默认配置合并即可。这也是官方的推荐做法!

如何挂载数据存储目录可以在Where to Store Data下找到:

在这里插入图片描述

这里明确说明,镜像中MySql的数据存储目录为/var/lib/mysql

注意点:

Docker挂载主机目录访问如果出现:

cannot open directory .: Permission denied

解决办法:在挂载目录后多加如下参数即可:

--privileged=true

使用该参数,container内的root拥有真正的root权限.

否则,container内的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

可以看到,容器myUbuntu以磁盘挂载的方式,挂载了一个宿主机目录。

此时,如果又有一个容器myUbuntu2是可以选择继承容器myUbuntu的卷的挂载规则的。

示例如下:

docker run -it --privileged=true --volumes-from myUbuntu --name myUbuntu2 ubuntu

这样一来容器myUbuntu2就继承了容器myUbuntu的卷的挂载规则。

容器myUbuntu的卷的挂载规则容器myUbuntu2就统统都有了。

八、数据挂载和磁盘挂载的优缺点

6.1 数据挂载方式

使用数据卷挂载的方式,Docker会自动在宿主机上帮我们创建数据卷对应的真实目录。

容器挂载时只需要挂载到数据卷上,而不用关心数据卷指向的真实目录在哪里。

即使将来容器被删除了,数据卷中或者宿主机挂载到容器的目录中的内容是不会随着容器的删除而丢失的。

优点:这种方式相当于把挂载全部交给Docker本身处理,方便快捷。

缺点:真实挂载目录由Docker生成,目录较深,不方便查找。

6.2 磁盘挂载方式

优点:目录和文件更好找也更好维护,并且能直接把目录或者文件挂载到容器上。

缺点:目录和文件需要我们自行创建和维护。

6.3 小结

  • 数据卷挂载耦合度低,由Docker自动化管理目录,但是目录较深,不方便查找。
  • 目录挂载耦合度高,需要我们自己管理目录,不过目录容易寻找查看。

如何选用挂载方式,结合实际情况即可。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 Docker 数据的进阶篇,我可以为你提供以下内容: 1. 数据的类型 Docker 数据有三种类型:主机挂载、匿名命名。其中,主机挂载是将主机上的目录挂载容器中;匿名是在容器内部创建的临时命名则是给一个名字,并将其保存在 Docker 数据存储区中。 2. 数据的备份与恢复 我们可以使用 Docker Compose 中的 `docker-compose.yml` 文件来定义数据的备份和恢复。具体方法是,在 `volumes` 字段中定义及其备份路径,然后在 `services` 字段中指定容器和对应的名称。 例如: ``` version: "3" services: db: image: mysql volumes: - db_data:/var/lib/mysql command: --default-authentication-plugin=mysql_native_password backup: image: backup volumes: - /path/to/backup:/backup - db_data:/data/db command: backup.sh volumes: db_data: ``` 以上代码中,我们定义了一个 `db` 服务和一个 `backup` 服务。其中,`db` 服务使用了名为 `db_data` 的命名,并挂载容器的 `/var/lib/mysql` 目录中;`backup` 服务则使用了两个一个挂载到宿主机上的 `/path/to/backup` 目录,用于保存备份文件;另一个使用了 `db_data` 命名,并挂载容器的 `/data/db` 目录中,用于备份数据。最后,我们在 `backup` 服务中执行了备份脚本 `backup.sh`。 3. 数据的共享 我们可以将一个数据挂载到多个容器中,实现数据的共享。例如,我们可以将一个命名挂载到 `web` 和 `db` 两个服务中,这样它们就可以共享数据了。 ``` version: "3" services: web: image: nginx volumes: - web_data:/usr/share/nginx/html db: image: mysql volumes: - db_data:/var/lib/mysql - web_data:/var/www/html volumes: db_data: web_data: ``` 以上代码中,我们定义了一个 `web` 服务和一个 `db` 服务。其中,`web` 服务使用了名为 `web_data` 的命名挂载容器的 `/usr/share/nginx/html` 目录中;`db` 服务则使用了 `db_data` 和 `web_data` 两个,分别挂载容器的 `/var/lib/mysql` 和 `/var/www/html` 目录中,实现了数据的共享。 希望以上内容能够对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值