(一) 个人分层理解

在前文中 有过 拉取Mysql 最新版后 再拉取mysql 5.7.30在下载镜像的时候 提示有些文件已存在!

image-20200521213604103

其实 通过第二章 学习 拉取了许许多多镜像后 终于发现 无论什么镜像 在下载的时候 都不是一个下载进度条 都是多层 多个进度条下载 有的会提示 Already exists 好像 一个镜像被拆分成了 多层宝塔一般 同时分层下载。

个人理解 : 这种分层技术 是 docker 强大的功能点之一 会减少很多的冗余文件 每一个镜像 都设置为宝塔形,进行分层 。当某一个镜像 依赖于另一个镜像的分层 时会先判断 该层是否已存在 如果存在 则不下载 ,仅仅下载镜像所需的额外部分。 类似于盖楼房 一层一层的堆积 上层依赖于下层。 那么当删除镜像的时候呢 ,也会查看自己构成镜像的所有层 如果 自己的某层级在被另一个镜像所依赖(使用)则会忽略删除该层。

	正如咱上放的mysql  可能依赖于什么   (举个例子: centos 啊  xxxx等) 那么在第一次pull mysql 时 会判断当前docker 是否含有 这个centos 镜像分层  有的话 则不下载 ,继续下载mysql 镜像所必须要使用的其余分层。 然后一层一层的 下载完后 组成了一个完整的 mysql镜像。

当我们再次下载 mysql5.7.30的时候  可能 mysql:5.7.30 镜像与mysql 镜像 有使用到相同的层级 那么在pull  mysql:5.7.30的时候 会先查询docker 是否含有mysql:5.7.30所要使用的 镜像 ,经查询 发现果然 有的层已经是被在拉取 mysql的时候下载了 ,所以拉取5.7.30的时候回提示  Already exists,由于构建mysql5.7.30其余层没有 则继续下载新的其余的层级。

(二)数据卷的简单使用

(1)数据卷概念

docker 容器虽然好用 ,但是咱发现了一些问题

场景1: 比如,我在安装了mysql 并把mysql 作为数据源 在项目中使用 ,那么不想使用这个容器 或者这个容器出现问题 需要删除时 不是吧mysql 容器中的数据也删除了吗?? 这不就是我们产后说的,删库跑路吗。 需求:需要 容器数据持久化 或绑定到外部宿主机

场景2: 通过前文 发现了 容器中 无法使用一个Linux命令 ,例如 ll,vim,vi等 那么我们在修改一些配置文件时就很不方便 例如 修改redis ,mongo 等配置文件 ,还需要额外下载vim 等命令 ,每个容器都需要下载,且下载速非常缓慢,这样,肯定是不行的。 需求:外部修改 同步到容器 或类似于宿主机与容器间的端口映射

将宿主机中的某个目录,映射到容器中,这样,在容器中此目录下的修改,即便容器关闭,数据也会保留下来,供宿主机和其他容器访问。

数据卷是一个可供容器使用的特殊目录,它绕过文件系统,可以提供很多有用的特性:

- 数据卷可以在容器之间共享和重用

- 对数据卷的修改会立马生效

- 对数据卷的更新,不会影响镜像

- 卷会一直存在,直到没有容器使用

(2)数据卷的简单使用

在run 镜像的时候 使用-v 参数 来实现 宿主目录与虚拟机目录进行挂载映射

例如 启动一个redis 镜像 设置端口映射 设置别名为aa

docker run -d  -p 6888:6379 --name aaa -v /test:/data redis

发现咱们的宿主机 /test 目录已经与 aaa 容器 /data 目录挂载起来了

image-20200521221409765

使用xshell再打开一个窗口 进行同步测试

咱们在 容器中新建一个 qqqq.file 文件 ,查看 宿主机中 /test 目录下是否会自动添加

image-20200521221811218

我们再在容器中 输出语句到 qqqq.file中

在容器输出语句到 qqqq.file 也同步到了 外部的 /test目录下的 qqqq.file 文件

image-20200521222045795

那么容器内部 同步到外部 没什么问题了 咱再测测 外部文件同步内部容器

发现外部添加的 leilei.java 文件也同步到了容器内

image-20200521222230506

那么 咱们 关闭容器 是否还能进行同步呢?

首先ctrl+p+q退出容器后 在宿主机上编写 语句 然后从起容器进入内部查看-----发现也同步了

image-20200521222523702
特别需要注意的是:删除文件 也是同步的,无论是删除宿主机上文件 还是容器内部文件都会进行同步删除

咱将整合容器进行删除------
整个容器删除 数据不会同步 意思是 不会因为容器的删除 而删除其挂载在外部宿主机的目录
image-20200521223023732

那么做一个小的总结

容器内新建 删除 修改文件------------ 宿主机外部挂载的目录 同步

容器删除--------宿主机外部挂载的目录不会同步

(3)场景模拟:mysql 数据挂载同步验证

mysql 宰门开发中 是经常使用的菲关系型数据库,为了加深学习印象,所以咱来实战模拟一下 同步容器以及删除容器 好让以后心里有个底

查看自己的以及在运行的容器

image-20200523143915040

首先 pull 镜像 我这里拉取mysql:5.7.30 至于版本问题 可查看docker 镜像库:docker镜像库

docker pull mysql:5.7.30

再持久化运行 指定端口映射 数据卷挂载 设置密码启动

查看到官方 教学 发现 其指定密码时使用了**-e 参数** 此参数 为设置环境变量的意思

image-20200523144127855

既然咱们要挂载 mysql数据目录 ,那肯定的知道 容器中 mysql 的配置文件路径一个数据存储路径吧!

得 咱不知道 ,浏览官网吧 ,官网果然是上手新事物的第一老师啊!

查阅后 发现 mysql 容器的 配置文件路径在 /etc/mysql/conf.d 数据存储路径在/var/lib/mysql

image-20200523144429219

image-20200523144530210

那么 咱们运行 Mysql的容器的整个命令为

docker run -d -p 7000:3306 -v /docker/mysql/conf:/etc/mysql/conf.d -v /docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.30

image-20200523145342405

运行成功后 使用咱们的 Navcat 查看

image-20200523145401300

然后再看我们挂载的 /docker/mysql 下时候有容器中的文件-----------果然是有的

image-20200523145532156

咱们使用navicat 创建一个新的数据库 并在数据库中创建一张表并插入数据 ----然后到 挂载的宿主机目录以及 容器中查看

image-20200523145928106

宿主机目录是有的了

image-20200523150051579

咱再查看 容器内

image-20200523150255534

为了同步性 我们再容器中吧新建的 leilei 库给删除

image-20200523150439828

刷新后 报错 找不到 ‘’‘leilei’ 数据库 说明容器中数据已经被删除掉了 那么我们查看 宿主机总对应挂载的目录/docker/mysql/data/下时候还含有 leilei 文件夹

image-20200523150547311

image-20200523150849680

那么 咱们说的 数据持久化 到底是什么呢 ?

容器中 新增数据 --同步到了宿主机, 删除数据 --还是同步到了宿主机

咱们最后再进行一个验证
向容器中 添加数据后 删除容器 ,然后在运行一个全新的容器实例 将其数据绑定到 上一个容器数据 目录 ,查看数据是否会被丢失

1.在当前容器中添加数据 -----我这里还是以naicat 添加数据库添加表做演示

添加Learn 数据库 添加表 student 并插入一条数据

image-20200523151507356

2.删除当前容器 -------为了更好演示 直接删除所有容器,,,

image-20200523151622740

3.创建新的容器实例 将其数据目录配置目录 与之前Mysql 容器绑定 并指点端口6888

image-20200523152217924

  1. navicat 链接 查看数据

image-20200523152355314

发现数据还是回来了 ----那么至少证明了 删除整个容器 做不到 删库 更别说跑路了,,,,,,

image-20200523152428989

复制2小标题的总结, 特别特别需要注意以及牢记

容器内新建 删除 修改文件:宿主机外部挂载的目录 同步!!!!要是真有人搞事 删除了 容器内部中挂载目录下的数据 那真的是要删库跑路了。
容器整个删除:宿主机外部挂载的目录不会同步!!!!

(三)数据卷挂载方式

数据卷挂载方式有:匿名挂载,具名挂载 ,指定路径挂载

我们上方用的 -v 宿主机路径:容器内路径 那么这种 很明显 是指定路径挂载其明确的指定了 容器的目录 挂载到了宿主机的哪个位置

首先 我们可以查看 所有挂载卷列表

docker volume ls

image-20200523155518180

匿名挂载

像目前此列表 展示出的所有卷 都是匿名挂载 ------- 一串唯一且随机的编码 直观上看 不知道其具体的名字 以及挂载到宿主机上的路径

我们来使用命令来匿名挂载一个容器 — 使用 -v 参数的时候 仅仅指定 容器内部挂载路径 不指定外部 这种命令挂载的卷 都是匿名挂载

# -v 后 未指定宿主机路径以及挂载名
docker run -d -v /data redis

image-20200523155855175

具名挂载

---- 即在容器与宿主机进行挂载的时候指定一个名字

#-v 参数后 指点挂载的卷名:/容器内路径
docker run -d -v names:/data --name jumingguazai  redis

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bvWJFB8Y-1666755279804)(https://leileidev.oss-cn-chengdu.aliyuncs.com/img/aHR0cHM6Ly9sZWlsZWlkZXYub3NzLWNuLWNoZW5nZHUuYWxpeXVuY3MuY29tL2ltZy9pbWFnZS0yMDIwMDUyMzE2MDU0Njc4NS5wbmc?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,size_35,text_bGVpbGVp,color_FF6600,shadow_50,t_100,g_se,x_600,y_20)]

那么 怎么查看卷所在的宿主机位置呢?

docker volume inspect 卷名

image-20200523161100766

我们在挂载的时候 如果未指定目录 其都会挂载到 默认目录 /var/lib/docker/volumes/ 下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RONNADus-1666755279805)(https://leileidev.oss-cn-chengdu.aliyuncs.com/img/aHR0cHM6Ly9sZWlsZWlkZXYub3NzLWNuLWNoZW5nZHUuYWxpeXVuY3MuY29tL2ltZy9pbWFnZS0yMDIwMDUyMzE2MTMzMDYzNS5wbmc?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,size_35,text_bGVpbGVp,color_FF6600,shadow_50,t_100,g_se,x_600,y_20)]

在官网 查看 挂载的 时候 发现 挂载 路径后 还可以添加 :ro 或者 :rw 其实这两个 代表中数据卷 在容器目录中的操作权限

ro: read only 尽可读 容器中 不能在 数据卷挂载目录 进行写入 仅可在宿主机上操作

**rw:read write 可读可写 ** 宿主机 容器中 均可操作 数据卷挂载所在目录

使用示例

docker run -d -v /docker/redis:/data:rw  --name redisrotest  redis

我们挂载的时候 不写 其实默认的是使用了 rw 权限 可读 可写

(四)数据卷常用命令

image-20221026111937805

(五)容器间 数据共享 (同步)

我们前边已经使用 -v 指定路径挂载使容器与宿主机之间进行了数据同步,现在呢开始学习 容器与容器之间使用数据卷进行数据同步

接着使用之前的容器

image-20200523204449264查看容器详细信息

docker inspect 容器Id/容器别名

image-20200523204637112

发现容器内部的 /data 与宿主机的/docker/redis 挂载的

容器之间 使用数据卷挂载命令 --volumes-from 要挂载容器ID

docker run -it --name redis02 --volumes-from redisrotest redis /bin/bash

image-20200523210112386

这个时候 容器一 就相当于是 容器二的父容器

我们还可以再创建一个容器redis03 使其成为容器二的子级容器

docker run -it --volumes-from redis02 --name redis03 redis /bin/bash

image-20200523215539586

几幅图 可以看出 我创建了 redisrotest (容器一) 然后 通过redis 镜像 构建容器二(redis02) 并使用 --volumes-from 绑定到容器一 那么此时 redisrotest 则为 redis02的父级容器 由于数据卷的缘故 他们数据是相互同步的,且同步到宿主机 ,然后呢我又创建了一个容器三(redis03)使redis02 成为其子级 那么 三个容器间 与宿主机则相互串起来了了 数据达到了同步到效果

即:

image-20200523220910880

那么 到了这里 数据卷 容器间 数据卷使用 就结束了 明天开始冲击学习 dockerfile!!!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐