目录

一、技术需求

二、 实现挂载的两种方法

2.1 方式(一)run -v 命令挂载

1. 指定路径挂载

2. 具名挂载(最常用!)

3. 匿名挂载

4. 拓展

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的父容器。

  1. 首先,最初始的docker01要挂载到宿主机上
  2. docker02 --volumes-from docker01
  3. docker03 --volumes-from docker02/01 
  4. docker04 --volumes-from docker03/02/01 
  5. ......

尽管docker02和03是依附于01,但是01死了,02,03和宿主机之间依然同步。看上面那张图就够了,就像病毒一样,只要残留一个,就能保留下所有数据。此时,我们杀掉docker01,然后在docker02的/December/must/be/wonderful目录里新建一个happy2023.txt文件。然后去docker03下查看

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐