docker 文件分层与数据卷挂载
Docker学习之路(三) docker 文件 分层理解 数据卷 数据同步(一) 个人分层理解在前文中 有过 拉取Mysql 最新版后 再拉取mysql 5.7.30在下载镜像的时候 提示有些文件已存在!其实 通过第二章 学习 拉取了许许多多镜像后 终于发现 无论什么镜像 在下载的时候 都不是一个下载进度条 都是多层 多个进度条下载 有的会提示 Already exists好像 一个镜像被拆分成了
文章目录
(一) 个人分层理解
在前文中 有过 拉取Mysql 最新版后 再拉取mysql 5.7.30在下载镜像的时候 提示有些文件已存在!
其实 通过第二章 学习 拉取了许许多多镜像后 终于发现 无论什么镜像 在下载的时候 都不是一个下载进度条 都是多层 多个进度条下载 有的会提示 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 目录挂载起来了
使用xshell再打开一个窗口 进行同步测试
咱们在 容器中新建一个 qqqq.file 文件 ,查看 宿主机中 /test 目录下是否会自动添加
我们再在容器中 输出语句到 qqqq.file中
在容器输出语句到 qqqq.file 也同步到了 外部的 /test目录下的 qqqq.file 文件
那么容器内部 同步到外部 没什么问题了 咱再测测 外部文件同步内部容器
发现外部添加的 leilei.java 文件也同步到了容器内
那么 咱们 关闭容器 是否还能进行同步呢?
首先ctrl+p+q退出容器后 在宿主机上编写 语句 然后从起容器进入内部查看-----发现也同步了
特别需要注意的是:删除文件 也是同步的,无论是删除宿主机上文件 还是容器内部文件都会进行同步删除
咱将整合容器进行删除------
整个容器删除 数据不会同步 意思是 不会因为容器的删除 而删除其挂载在外部宿主机的目录
那么做一个小的总结
容器内新建 删除 修改文件------------ 宿主机外部挂载的目录 同步
容器删除--------宿主机外部挂载的目录不会同步
(3)场景模拟:mysql 数据挂载同步验证
mysql 宰门开发中 是经常使用的菲关系型数据库,为了加深学习印象,所以咱来实战模拟一下 同步容器以及删除容器 好让以后心里有个底
查看自己的以及在运行的容器
首先 pull 镜像 我这里拉取mysql:5.7.30 至于版本问题 可查看docker 镜像库:docker镜像库
docker pull mysql:5.7.30
再持久化运行 指定端口映射 数据卷挂载 设置密码启动
查看到官方 教学 发现 其指定密码时使用了**-e 参数** 此参数 为设置环境变量的意思
既然咱们要挂载 mysql数据目录 ,那肯定的知道 容器中 mysql 的配置文件路径一个数据存储路径吧!
得 咱不知道 ,浏览官网吧 ,官网果然是上手新事物的第一老师啊!
查阅后 发现 mysql 容器的 配置文件路径在 /etc/mysql/conf.d 数据存储路径在/var/lib/mysql
那么 咱们运行 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
运行成功后 使用咱们的 Navcat 查看
然后再看我们挂载的 /docker/mysql 下时候有容器中的文件-----------果然是有的
咱们使用navicat 创建一个新的数据库 并在数据库中创建一张表并插入数据 ----然后到 挂载的宿主机目录以及 容器中查看
宿主机目录是有的了
咱再查看 容器内
为了同步性 我们再容器中吧新建的 leilei 库给删除
刷新后 报错 找不到 ‘’‘leilei’ 数据库 说明容器中数据已经被删除掉了 那么我们查看 宿主机总对应挂载的目录/docker/mysql/data/下时候还含有 leilei 文件夹
那么 咱们说的 数据持久化 到底是什么呢 ?
容器中 新增数据 --同步到了宿主机, 删除数据 --还是同步到了宿主机
咱们最后再进行一个验证
向容器中 添加数据后 删除容器 ,然后在运行一个全新的容器实例 将其数据绑定到 上一个容器数据 目录 ,查看数据是否会被丢失
1.在当前容器中添加数据 -----我这里还是以naicat 添加数据库添加表做演示
添加Learn 数据库 添加表 student 并插入一条数据
2.删除当前容器 -------为了更好演示 直接删除所有容器,,,
3.创建新的容器实例 将其数据目录配置目录 与之前Mysql 容器绑定 并指点端口6888
- navicat 链接 查看数据
发现数据还是回来了 ----那么至少证明了 删除整个容器 做不到 删库 更别说跑路了,,,,,,
复制2小标题的总结, 特别特别需要注意以及牢记
容器内新建 删除 修改文件:宿主机外部挂载的目录 同步!!!!要是真有人搞事 删除了 容器内部中挂载目录下的数据 那真的是要删库跑路了。
容器整个删除:宿主机外部挂载的目录不会同步!!!!
(三)数据卷挂载方式
数据卷挂载方式有:匿名挂载,具名挂载 ,指定路径挂载
我们上方用的 -v 宿主机路径:容器内路径 那么这种 很明显 是指定路径挂载了 其明确的指定了 容器的目录 挂载到了宿主机的哪个位置
首先 我们可以查看 所有挂载卷列表
docker volume ls
匿名挂载
像目前此列表 展示出的所有卷 都是匿名挂载 ------- 一串唯一且随机的编码 直观上看 不知道其具体的名字 以及挂载到宿主机上的路径
我们来使用命令来匿名挂载一个容器 — 使用 -v 参数的时候 仅仅指定 容器内部挂载路径 不指定外部 这种命令挂载的卷 都是匿名挂载
# -v 后 未指定宿主机路径以及挂载名
docker run -d -v /data redis
具名挂载
---- 即在容器与宿主机进行挂载的时候指定一个名字
#-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 卷名
我们在挂载的时候 如果未指定目录 其都会挂载到 默认目录 /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 权限 可读 可写
(四)数据卷常用命令
(五)容器间 数据共享 (同步)
我们前边已经使用 -v 指定路径挂载使容器与宿主机之间进行了数据同步,现在呢开始学习 容器与容器之间使用数据卷进行数据同步
接着使用之前的容器
查看容器详细信息
docker inspect 容器Id/容器别名
发现容器内部的 /data 与宿主机的/docker/redis 挂载的
容器之间 使用数据卷挂载命令 --volumes-from 要挂载容器ID
docker run -it --name redis02 --volumes-from redisrotest redis /bin/bash
这个时候 容器一 就相当于是 容器二的父容器
我们还可以再创建一个容器redis03 使其成为容器二的子级容器
docker run -it --volumes-from redis02 --name redis03 redis /bin/bash
几幅图 可以看出 我创建了 redisrotest (容器一) 然后 通过redis 镜像 构建容器二(redis02) 并使用 --volumes-from 绑定到容器一 那么此时 redisrotest 则为 redis02的父级容器 由于数据卷的缘故 他们数据是相互同步的,且同步到宿主机 ,然后呢我又创建了一个容器三(redis03)使redis02 成为其子级 那么 三个容器间 与宿主机则相互串起来了了 数据达到了同步到效果
即:
那么 到了这里 数据卷 容器间 数据卷使用 就结束了 明天开始冲击学习 dockerfile!!!
更多推荐
所有评论(0)