Docker(六)——挂载实现同步+实战
先来考虑这样两个问题如果我们的MySQL是用docker部署的。MySQL的数据存储在容器中,一旦我们把MySQL这个容器delete了,或者直接把整个docker删了。那么数据库的所有数据都丢了,这是不合理的。所以我们要求容器的数据能够存储在本地。容易通常是以后台的方式运行的,假如我们用部署了一个Nginx容器,每次修改Nginx配置文件都要进入容器,这是十分麻烦的。如果能在宿主机提供一个路径映
目录
2.2 方式(二)DockerFile (构建新镜像时常用这种方式!)
可以理解为VMware虚拟机和宿主机的“共享文件夹”
一、技术需求
先来考虑这样两个问题
问题(一):如果我们的MySQL是用docker部署的。MySQL的数据存储在容器中,一旦我们不小心把MySQL这个容器delete了。那么数据库的所有数据都丢了,这是不合理的。所以我们要求容器的数据能够存储在本地(实现数据的持久化)。
问题(二): 容易通常是以后台的方式运行的,假如我们用部署了一个Nginx容器,每次修改Nginx配置文件都要进入容器,这是十分麻烦的。如果能在宿主机提供一个路径映射,直接在宿主机上修改,然后同步到Nginx容器就好了。
这个技术就是——卷技术/挂载
容器可以看成一个小型Linux虚拟机,那么它也有自己的文件系统,使用挂载技术之前,容器的数据是存储在自己的文件系统内的,所以容器一旦被删除,容器存储的数据也就没有了。而挂载技术就是将容器的文件路径挂载到宿主机的文件系统路径上
1)实现容器和宿主机之间数据的同步(在容器更改文件可以同步到宿主机,在宿主机更改文件也可以同步到容器)
2)各个容器之间也能共享数据
二、 实现挂载的两种方法
2.1 方式(一)run -v 命令挂载
run -v 又存在3种方式:
1. 指定路径挂载: run -v /home/tomcat/webapps:/usr/local/tomcat/webapps
2. 具名挂载(推荐,常用):run -v tomcat-volume:/usr/local/tomcat/webapps
3.匿名挂载: run -v /usr/local/tomcat/webapps
1. 指定路径挂载
docker run -it -v /home/test:/home centos /bin/bash
# “:”表示映射关系, 将宿主机的/home/test目录映射到容器centos的/home目录
容器启动起来以后,我们可以通过docker inspect 容器id命令查看是否挂载成功,如果出现“Mounts”属性则挂载成功。
测试:容器->宿主机
测试:宿主机->容器
为什么容器停掉了,还能实现数据从宿主机到容器的同步呢?因为容器只是停掉了,但是没有被删除,别忘了stop是容器的一个状态。
tomcat实战测试
Docker(八)—— Dockerfile制作Tomcat镜像_玛丽莲茼蒿的博客-CSDN博客
MySQL实战测试
没跟着做,可以去看视频,不看也行
但是我们不常用这种方法,为什么呢?
指定路径名挂载的时候,我们是不是还要想“到底应该挂载到宿主机的什么路径下呢”,不仅要费脑想把它安排到宿主机的哪个目录下好,而且今天把容器1的卷挂载到/home/today目录下,明天把容器2的卷挂载到/var/tommorow目录下,最后挂来挂去记不得哪个容器挂到哪里去了。
如何解决避免这种麻烦呢?
那就都放在docker的工作目录下!也就是接下来要说的具名挂载和匿名挂载。
2. 具名挂载(最常用!)
无论是具名挂载还是匿名挂载都放在docker的工作目录/var/lib/docker/volume/下,具名是为了自定义数据卷文件夹的名字,匿名的话docker会分配一个默认的名字。
# 把容器内部的/usr/local/apache-tomcat-10.0.27/webapps/test目录挂载出来,起名为“diytomcat-volume”,就存放在/var/lib/docker/volume/diytomcat-volume/_data目录下。
[root@hadoop100 ~]# docker run -d -v diytomcat-volume:/usr/local/apache-tomcat-10.0.27/webapps/test diytomcat:0.1
测试:
我们把web资源放在_data目录下。
一点小思考+实践:
如果容器1使用具名挂载-v volume-test:/容器1指定的内部目录,docker会开一个/var/lib/docker/volume/volume-test/_data目录,我们把容器1杀死,这个目录会保留(这也是容器卷的意义所在呀,容器被不小心删掉,重要的数据还能留下来)。然后开一个容器2,也使用具名挂载-v volume-test:/容器2指定的内部目录,那么/var/lib/docker/volume/volume-test/_data的数据会被立马同步到容器2指定的目录,容器2沿用了这个目录,并不会为容器2新开一个volume-test(1)目录。
如果我们不杀死容器1就开始容器2。那么容器2和容器1便会共用这个目录,也就实现了两个容器之间的数据共享(但是后面我们会用数据卷容器的方式)!经过测试,容器2一旦删掉了某个文件,对应的容器1和宿主机都会删掉这个文件。
这也告诉我们了,具名挂载前要通过docker volume ls命令看一看,这个名字有没有其他容器用过,以防不小心和其他容器共用数据卷了。
3. 匿名挂载
# 把容器内部的/usr/local/apache-tomcat-10.0.27/webapps/test目录挂载出来,docker给一个默认的名字“xxxxxx”,就存放在/var/lib/docker/volume/xxxxxx/_data目录下。
[root@hadoop100 ~]# docker run -d -v /usr/local/apache-tomcat-10.0.27/webapps/test diytomcat:0.1
docker volume ls命令后可以看到, docker给数据卷分配了一个默认的名字。
我们再进入宿主机/var/lib/docker/volumes路径下,也可以看到数据卷分配的文件夹,以及文件夹下的_data文件。
4. 拓展
我们挂载的时候还可以指定容器对于数据卷的读写权限(以上三种方式都可以加)
- :ro 容器只能读
- :rw 容器可读可写
不指定的话默认用:rw
2.2 方式(二)DockerFile (构建新镜像时常用这种方式!)
首先想一个问题,上面三种挂载形式“指定路径挂载、具名挂载、匿名挂载”,用dockerfile都可以实现吗?
答案是只能实现匿名挂载。因为dockerfile是用来生成镜像的,如果在dockerfile里指明挂载的路径或者具名挂载,就把数据卷的路径写死了,那么由这个镜像生成的所有容器都挂载同一个目录下了,必须共享同一个目录了,哪有这种道理?所以dockerfile只能用来进行匿名挂载。
使用Dockerfile进行挂载和用docker run -v的3种方式进行挂载的区别在于,一旦使用Dockerfile进行挂载,镜像生成的每个容器都必须挂载。而-v可以不挂载。
FROM 镜像名
# 匿名挂载
VOLUME ["镜像内部的路径1","镜像内部的路径2","镜像内部的路径3",.......]
实战:
FROM centos
VOLUME ["/volume1","volume2"]
构建镜像,然后运行并进入镜像
那volume1和volume2被挂载到哪里去了呢?
我们inspect一下这个容器,找到啦!
三、数据卷容器
如何实现多个容器之间的数据同步,有两种方法
法(一):挂载到同一个宿主机数据卷(共享思想)
这种思想是我们在前面测出来的。docker01~03都挂载到同一个宿主机路径,这样docker02改动了数据,docker01,03和宿主机的数据都会同步修改。如果docker01被删掉了,并不影响docker02,03和宿主机的共享。
为什么不推荐用这种?
因为用匿名挂载无法实现。如果想要实现的话,必须具名挂载或者指定路径挂载。这也就要求,开启每一个容器的时候都要输入一遍名字或者路径,倘若某次疏忽输错了,就有一个容器没实现共享!而下面这种方法可以就不会出现这种错误!
法(二):数据卷容器思想(拷贝思想,用这个!)
首先,数据卷容器指的是一个容器。它为其他容器提供数据卷,称他为父容器或者数据卷容器。docker02通过docker run --volumes-from docker01挂载了docker01,那么docker01就是docker02的父容器。
- 首先,最初始的docker01要挂载到宿主机上
- docker02 --volumes-from docker01
- docker03 --volumes-from docker02/01
- docker04 --volumes-from docker03/02/01
- ......
尽管docker02和03是依附于01,但是01死了,02,03和宿主机之间依然同步。看上面那张图就够了,就像病毒一样,只要残留一个,就能保留下所有数据。此时,我们杀掉docker01,然后在docker02的/December/must/be/wonderful目录里新建一个happy2023.txt文件。然后去docker03下查看
更多推荐
所有评论(0)