Docker核心基础(二)挂载

本文详细介绍了Docker数据卷的使用,包括匿名挂载、具名挂载、数据卷容器的概念与实践。通过实例展示了如何使用数据卷实现MySQL的数据持久化,并探讨了通过`--volumes-from`实现多个容器间的数据共享和备份。此外,还提到了Dockerfile中使用`VOLUME`命令创建数据卷,以及数据卷容器在多容器数据同步中的作用和潜在问题。
摘要由CSDN通过智能技术生成

一、Volume(数据卷)

1.1 问题引出:

Docker容器中产生的数据在容器重启即丢失,对于存储系统或者有状态的应用,我们希望数据能够持久化下来,最典型的是数据库。不仅如此,我们还希望不同容器之间能够共享数据。
在这里插入图片描述
解决方案就是:数据卷,本质就是个挂载

1.2 命令

docker run -v 宿主机目录:容器目录
比如:
docker run --name tomcat0 -v /home/test:/home -p 8080:8080 -d tomcat:9.0

下面再举个栗子:
启动一个centos 容器,将容器内的 /home 目录和 宿主机的一个测试目录 /home/centosTest 映射起来。

[root@localhost test]# docker run --name mycentos -v /home/test:/home -d centos

实际上, 容器的 /home 和 宿主机的 /home/test 是同一个目录。在 容器的 /home 中修改 会映射到 宿主机的/home/test ; 宿主机 /home/test 的修改也会映射到 容器的 /home 。
即使是 删除掉这个容器,宿主机中的内容依然存在。

再来看一下容器的 mount信息 ,执行docker inspect ContainerID,截取其中 Mounts 如下。

  • type: bind 可以理解为 双向绑定
  • source: 宿主机目录
  • destination: 容器目录
    在这里插入图片描述

1.3 实战(MySQL)

需求:实现MySQL数据持久化功能

1、搜索并pull 镜像
2、启动
docker hub 中的启动命令:
$ docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
这个命令无法让容器中的数据持久化,我们使用下面这个语句启动:
docker run --name mysql01 -p 3306:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
着重看下下面两个卷映射:
-v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql

这是把 宿主机的 /home/mysql/conf 和 容器的/etc/mysql/conf.d “双向绑定”起来了;同时把宿主机/home/mysql/data 和 容器的 /var/lib/mysql 绑定起来。

分别进入到容器内部和宿主机的内部看数据:

在这里插入图片描述

3、测试连通OK
通过GUI工具连过去看看
4、测试创建新Schema OK
5、删除容器看数据是否存在于宿主机
删除容器

二、具名挂载和匿名挂载

具名挂载: 给挂载取了个名字
匿名挂载:挂载没名字(docker内部会生成一个字符串作为名字)
1、匿名挂载举个栗子:

  • 启动匿名挂载的Nginx (随机指定端口了)
    docker run --name nginx01 -d -P -v /etc/nginx nginx
    这里的 -v /etc/nginx容器内 的 路径,由于是匿名挂载,因此并不再指定 宿主机内的目录

  • docker volume ls 查看挂载的卷

    [root@localhost ~]# docker volume ls
    DRIVER    VOLUME NAME
    ...
    local     c1baa4089155de6a7245595288f2c3ebaa63722563af898a4091394769f7937c
    local     portainer_data
    

    这里有 多个 挂载的卷,Nginx 挂载的卷是其中一个。
    2、具名挂载再举个栗子

  • docker run --name nginx02 -d -P -v juming-nginx-volume:/etc/nginx nginx

    得到结果:

    [root@localhost ~]# docker run --name nginx02 -d -P -v juming-nginx-volume:/etc/nginx nginx
    f015fce75db3b5023fc98227d26f303e0ed7ef14eeafa90d5b0c9045969293f9
    [root@localhost ~]# docker volume ls
    DRIVER    VOLUME NAME
    ...
    local     c1baa4089155de6a7245595288f2c3ebaa63722563af898a4091394769f7937c
    local     juming-nginx-volume
    local     portainer_data
    

    看下 juming-nginx-volume 这个卷具体信息(挂到了哪里):
    docker volume inspect juming-nginx-volume
    在这里插入图片描述
    截图中的 MountPoint 就是 卷的挂载点。 /var/lib/docker/volumes/ 不仅是这个例子,而是docker 在默认情况下挂载卷的存放位置。
    在这里插入图片描述
    3、如何区分 是匿名还是具名挂载,还是指定路径挂载
    通过-v参数判断:

    • -v 卷名:容器内目录路径 --> 这是具名挂载
    • -v 容器内目录路径 --> 这是匿名挂载
    • -v /宿主机路径:容器内目录路径 -->这是 指定路径挂载

4、volume 的 rw ro
通过指定 -v 容器内路径,ro rw 可改变读写权限
无论是匿名、具名,还是指定路径挂载,都可以指定rw ro权限。

docker run --name nginx02 -d -P -v juming-nginx-volume:/etc/nginx:ro nginx
docker run --name nginx02 -d -P -v juming-nginx-volume:/etc/nginx:rw nginx

指定了ro的挂载:只能从宿主机操作,容器没有写卷的权限
指定了rw的挂载:宿主机、容器均可以读写

三、docker file初体验

Dockerfile : 就是构建Image的描述文件(命令脚本)。通过这个脚本,可以生成镜像,镜像是一层层的(UFS),脚本 命令是一个个的,每个脚本命令就会产生一层镜像

举个栗子:创建一个DockerFile,制作出 一个自己的镜像

第一步:创建一个dockfile ,内容如下
[root@localhost xiaohe-test]# cat dockerfile1 
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "..end.."
CMD /bin/bash

第二步: 执行 docker build 【注意最后有个 . 表示 当前的 build context】
[root@localhost xiaohe-test]# docker build -f dockerfile1 -t xiaohe/centos:01 .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos
 ---> 300e315adb2f
Step 2/4 : VOLUME ["volume01","volume02"]
 ---> Running in 15d62a5445bd
Removing intermediate container 15d62a5445bd
 ---> fd5b5d9fede3
Step 3/4 : CMD echo "..end.."
 ---> Running in 17bec299f276
Removing intermediate container 17bec299f276
 ---> 724156c85227
Step 4/4 : CMD /bin/bash
 ---> Running in 978558bfe4e3
Removing intermediate container 978558bfe4e3
 ---> 2a4be065fc65
Successfully built 2a4be065fc65
Successfully tagged xiaohe/centos:01

看这里分了四步,对应到dockerfile中的四个命令。每步都执行成功后,打了个 xiaohe/centos:01
[root@localhost xiaohe-test]# docker images
REPOSITORY               TAG       IMAGE ID       CREATED         SIZE
xiaohe/centos            01        2a4be065fc65   8 minutes ago   209MB
mytomcat                 02        2f6f33afc42c   27 hours ago    654MB

最后看确实生成了自己打的镜像。

接着这个栗子,从 自己的打的xiaohe/centos 拉起一个容器。有意思的是,我们在DockerFile VOLUME 出来的 volume01volume02 也存在。在这里插入图片描述
既然是容器内目录,那它映射到宿主机的什么目录呢?
docker inspect ContainerID ,发现到了Mount信息:原来是匿名挂载了 /var/lib/docker/volumes/ContainerID/_data这个目录!!!
在这里插入图片描述

看到这里,我们总结下:两种挂载卷的方式

  • 直接在docker run的时候使用 -v 参数挂载
  • 在生成镜像的时候指定命令 VOLUME

四、 数据卷 容器

啥是数据卷容器?说白了:利用某个容器给别的容器共享数据
在这里插入图片描述

4.1 举第一个栗子

利用前面一节自己制造的镜像xiaohe/centos拉起三个容器docker01、docker02、docker03;其中docker01 是数据卷容器:docker02会“自动同步” docker01 数据卷中的内容。

1、启动 父容器docker01
在这里插入图片描述
【注:ctrl P Q 退出容器console,但保持容器进程】

2、启动 子容器docker02
在这里插入图片描述
成功启动docker02后,看volume01 中已经有了在前一步中创建的 a.txt 测试文件。
3、在子容器docker 02 中创建新测试文件b.txt,看能不能同步到父容器中
在这里插入图片描述
由此可见: 默认情况下 --volumes-from实现的是“双向绑定”

4、目前只是docker02 --volumes-from docker01 ;下面测试 docker03 --volumes-from docker01 ,即一个父容器下多个子容器。
在这里插入图片描述
可以看到,docker01 中创建的 a.txt ,docker02 中创建的b.txt ,都被“同步”到docker03

5、做个测试:假如docker02被 rm 了,那docker01 docker03 中还能找到的之前创建的 a.txt b.txt 测试文件吗? 答案是 Yes!
在这里插入图片描述
6、再做个测试:假如 docker01 (父容器)被删了,那 仅剩的 docker03 还能找到的之前创建的 a.txt b.txt 测试文件吗? 答案也是 Yes!
在这里插入图片描述
7、看起来: docker01 docker02 docker03 共享卷不仅实现了数据的“共享”,还实现了数据的“备份”

4.2 举第二个栗子(多个MySQL同步数据)

第一个msyql 实例:
docker run --name mysql01 -p 3306:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

第二个MySQL:
docker run --name mysql02 -p 3307:3306 --volumes-from mysql01 -e  MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

我们再去mysql02  /home/mysql/data  下加一个测试文件  data_test.txt。发现数据确实存在于 mysql01  /home/mysql/data 下面。

看MySQL01 的挂载:
在这里插入图片描述

再看MySQL 02 的挂载:
在这里插入图片描述
从截图发现:
两个MySQL 容器,实际上是 mount到了同一个 宿主机目录!这个点很关键: 2个MySQL进程共同操作同一份数据目录,往往会有冲突产生。我们观察到 mysql 02 进程在运行一段时间后就会报异常并退出。【假如两个容器在不同的宿主机上,那么应该不会有这个问题】
对于MySQL这种有状态(存储系统)的应用,利用docker部署应格外注意。
(?可能有完备的方案了,笔者目前还没研究)
在这里插入图片描述

4.3 小结

1、
--volumes-from实现了多个容器之间的数据备份(不仅仅是共享)
在这里插入图片描述
2、有两种方式实现挂载:

  • docker run -v :
    • 匿名
    • 具名
    • 指定目录挂载
  • dockerfile中用 VOLUME 命令指定数据卷,打出镜像,拉起容器,即实现挂载

3、docker run --volumes-from 实现数据备份和同步
使用 --volumes-from关联的容器,只要至少一个不删除,数据就能保留一份。如果父容器 是挂载了 宿主机目录,即使所有容器删除了,数据依然存在。

4、不同宿主机上的容器也可以利用 --volumes-from 实现数据备份和同步,但需要容器之间连通(还需要注意带宽?)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值