Docker存储Volume,Docker数据持久化。Docker目录 电脑版发表于:2022/9/1 11:44 tn2>容器默认的数据读写操作在容器的存储层,当容器被删除时其上的数据将会丢失。所以我们应该尽量保证容器存储层不发生写操作,不然我们存储的数据很容易随着容器的删除而丢失,为了实现数据的持久化存储我们需要选择一种方案来保存数据。目前实现该方案的主要有Volumes 、 Bind mounts 、 tmpfs mounts,下面我们主要介绍Volumes与Bind mounts tn4>**volumes数据卷:** docker管理宿主机文件系统的一部分,通常存储在(/var/lib/docker/volumes)中,提供很多有用的特性: 1:数据卷可以在容器之间共享和重用,多个容器共享Volumes更安全 2:对数据卷的修改会立马生效 3:对数据卷的更新,不会影响镜像 4:数据卷默认会一直存在,即使容器被删除 5: Volumes更容易备份和移植。 6: 可以通过Docker CLI或API进行管理 7: Volumes可以无区别的工作中Windows和Linux下 8:当容器外的对应目录是空的,volume会先将容器内的内容拷贝到容器外目录,而mount会将外部的目录覆盖容器内部目录,内部的文件会被清空。相当于两种挂载方式处理文件是相反的,一种是把内部的复制到外部,一种是把外部的文件覆盖到内部 9:volume 是docker的宿主机文件系统一部分,只有docker可以进行更改,其他进程不能修改 tn5>**bind mounts挂载主机目录:** 将宿主机上的任意位置的文件或者目录挂在到容器 (--mount type=bind,src=源目录,dst=目标目录) 1:mount方式会将外部的目录覆盖容器内部目录,内部的文件会被清空。不管外部目录有没有文件内部目录的文件都会被清空,如果外部有文件就被外部的文件给复制出来。所以如果是把容器的内部的文件映射出来在外部使用,更推荐使用Volumes方式,但是如果镜像会经常更新,而以前持久化的数据存储在外边,如果使用Volumes方式新打包的镜像启动容器就会覆盖以前的内容,所以需要根据实际情况选择挂载方式。 2:bind mounts 是挂载在宿主机文件系统的任意位置,除了docker所有进程都可以进行修改 3:bind mount可以直接挂载文件,例如挂载nginx容器的配置文件:nginx.conf。 类似于配置文件这种单文件方式不太适合使用volume,可以使用bind mount,但由于config文件中包含一些类似于数据库密码等敏感信息,因此推荐使用tmpfs。 ## Volume管理 **1) 使用命令创建一个Volume。如图6.5所示** ``` docker volume create my-nginx-volume ``` ![](https://img.tnblog.net/arcimg/aojiancc2/74212706e80f49dda43a726094a676fa.png) <center>图6.5</center> **2) 使用命令查看Volumes。如图6.6所示** ``` docker volume ls ``` ![](https://img.tnblog.net/arcimg/aojiancc2/e42ba7f0fca24697a46db5996e80d25a.png) <center>图6.6</center> 可以使用如下命令查看volume详情,如图6.7所示。 ``` |docker volume inspect my-nginx-volume| ``` ![](https://img.tnblog.net/arcimg/aojiancc2/dd3066b8d2e946bd8c2eb51ad227ddb8.png) <center>图6.7</center> tn2>我们可以看到创建的my-nginx-volume 目录保存在/var/lib/docker/volumes/下,以后所有针对该 Volume 的写数据都会保存在目录/var/lib/docker/volumes/my-nginx-volume/\_data中。 **3) 删除一个指定名称的Volume。如图6.8所示** ``` docker volume rm my-nginx-volume ``` ![](https://img.tnblog.net/arcimg/aojiancc2/b71fabbc0c664f56921a70ee9e262f55.png) <center>图6.8</center> 删除后我们再次查看了一下Volume,可以看到刚刚创建的Volume已经被删除掉了 **4) 删除所有未使用的 Volumes** 我们可以先创建几个Volume,如图6.9所示。 ``` docker volume create my-volume-test-1 docker volume create my-volume-test-2 docker volume create my-volume-test-3 ``` ![](https://img.tnblog.net/arcimg/aojiancc2/3f88d42265744763b58bcb424cd88880.png) <center>图6.9</center> 查看一下刚刚创建的Volume,如图6.10所示。 ``` docker volume ls ``` ![](https://img.tnblog.net/arcimg/aojiancc2/41243014ad574e3f92b8cdeb10514d88.png) <center>图6.10</center> 使用命令执行删除所有未使用的 Volumes,如图6.11所示。 ``` docker volume prune ``` ![](https://img.tnblog.net/arcimg/aojiancc2/91bc9c791f5049ebb216210002c48967.png) <center>图6.11</center> tn2>删除后我们再次查看了一下Volume,可以看到很多的Volume已经被删除掉了,只剩下两个,而且执行的时候会让你输入一个y或者n进行确定和取消,因为该命令可能会造成一些误删除,所以需要用户的确认。 ## 挂载数据卷到容器目录 **1) 运行容器时通过指定--mount 参数来使用 Volume** 我们先创建一个Volume,如图6.12所示。 ``` docker volume create my-nginx-volume ``` ![](https://img.tnblog.net/arcimg/aojiancc2/34f743c3f07d48e19ce0d70030954699.png) <center>图6.12</center> 然后运行容器的时候通过指定--mount 参数来使用 Volume,如图6.13所示。 ``` docker run -d \ --name=nginxtest \ --mount source=my-nginx-volume,destination=/usr/share/nginx/html \ nginx:latest ``` ![](https://img.tnblog.net/arcimg/aojiancc2/323b46d7b5a744789c45c6a436400aba.png) <center>图6.13</center> source 指定 volume,destination 指定容器内的文件或文件夹。 tn2>挂载成功后,容器从 /usr/share/nginx/html 目录下读取或写入数据,实际上都是从宿主机的 my-nginx-volume 数据卷中读取或写入数据。因此 Volumes 或 Bind mounts 也可以看作是容器和宿主机共享文件的一种方式。 运行成功后可以查询一下刚刚启动的容器,如图6.14所示。 ![](https://img.tnblog.net/arcimg/aojiancc2/a12ca73f8d124c59935b18b6f712fc2c.png) <center>图6.14</center> **2) 运行容器时通过指定 -v参数来使用 Volume** 我们先创建一个Volume,如图6.15所示。 ``` docker volume create my-nginx-volume-2 ``` ![](https://img.tnblog.net/arcimg/aojiancc2/b4368d1cee5c4ccd80b7ce3425a7c73c.png) <center>图6.15</center> 然后运行容器的时候通过指定--v 参数来使用 Volume,如图6.16所示。 ``` docker run -d \ --name=nginxtest-2 \ -v my-nginx-volume-2:/usr/share/nginx/html \ nginx:latest ``` ![](https://img.tnblog.net/arcimg/aojiancc2/d4e3996298ba4d73b9433db21752cdc6.png) <center>图6.16</center> -v 参数使用冒号分割 source 和 destination,冒号前半部分是 source,后半部分是 destination。 注意如果你挂载的数据卷不存在,Docker 会自动创建它,所以通常不需要手动去创建数据卷 如果容器中的待挂载的目录不是一个空目录,那么该目录下的文件会被复制到数据卷中。Bind mounts模式下,宿主机上的目录总会覆盖容器中的待挂载目录 -v 参数和 --mount 参数总的来说功能几乎一样,唯一的区别是在运行一个 service 时只能够使用--mount 参数来挂载数据卷。 **3) 查看一下上面我们使用的数据卷,如图6.17所示** ``` docker volume ls ``` ![](https://img.tnblog.net/arcimg/aojiancc2/5109043f614844c087096865f27ffb28.png) <center>图6.17</center> 通过如下命令查看volume详情,可以看volume使用的目录,如图6.18所示。 ``` docker volume inspect my-nginx-volume ``` ![](https://img.tnblog.net/arcimg/aojiancc2/47de2051c5b64e84bb26f9b63b6af019.png) <center>图6.18</center> 可以通过如下进入volume使用的目录查看文件,如图6.19所示。 ``` cd /var/lib/docker/volumes/my-nginx-volume/_data ls ``` ![](https://img.tnblog.net/arcimg/aojiancc2/1990e253b8974511b06757472a068ea8.png) <center>图6.19</center> 可以看到有个50x.html与index.html 查看一下index.html的内容,如图6.20所示。 ``` cat index.html ``` ![](https://img.tnblog.net/arcimg/aojiancc2/99f6ca7e593b4139ac2af8eb6d85bd1f.png) <center>图6.20</center> 可以看到就是nginx里边的起始页 4) 修改挂载目录内容,测试数据。 重新运行容器,指定一下端口,如图6.21所示。 ``` docker run -d \ --name=nginxtest-3 \ -p 9000:80 \ -v my-nginx-volume-3:/usr/share/nginx/html \ nginx:latest ``` ![](https://img.tnblog.net/arcimg/aojiancc2/8a9d2b0b89e944a6b1d79a8cc388178f.png) <center>图6.21</center> 访问指定映射的9000端口,如图6.22所示。 ![](https://img.tnblog.net/arcimg/aojiancc2/58ea45ce43af4b47a8d76337e845d481.png) <center>图6.22</center> 查看刚刚的挂载卷与对应的目录,如图6.23所示。 ![](https://img.tnblog.net/arcimg/aojiancc2/f58e336ee19544d9aa416977075d633b.png) <center>图6.23</center> 进入volume使用的目录查看文件,如图6.24所示。 ``` cd /var/lib/docker/volumes/my-nginx-volume-3/_data ls ``` ![](https://img.tnblog.net/arcimg/aojiancc2/3ce9d4cf67714b58a3db862a4bf4357c.png) <center>图6.24</center> 使用vi命令修改index.html文件 ``` vi index.html ``` 把提示语句修改一点即可,如图6.25所示。 ![](https://img.tnblog.net/arcimg/aojiancc2/7f0b8afada31405bba80ba4a7df8f7ff.png) <center>图6.25</center> 然后在访问数据已经变化了,如图6.26所示。证明我们的挂载已经成功了,因为我们并没有进入容器内部修改,而是通过在容器外部修改达到修改内部资源的效果。 ![](https://img.tnblog.net/arcimg/aojiancc2/3158e24343d74368a96d9e50874a820c.png) <center>图6.26</center> ## bind mounts挂载主机目录 tn2>这种挂载比较简单,可以挂载系统盘的任意可用目录,直接挂载就可以。如果挂载的目录不存在也会自动创建。 **比如运行nginx的时候挂载目录html出来** ``` docker run -d \ --name=mynginx \ -p 8000:80 \ -v ~/aj/nginx-html:/usr/share/nginx/html \ nginx ``` 又比如挂载.net6项目下面的wwwroot目录下个某个文件 ``` docker run --name=wy_jbland_api \ -p 8003:8003 \ -v ~/fb/wy_jbland_api_volumne_uploads:/app/wwwroot/uploads \ wy_jbland_api:v1 ``` tn4>注意:当容器外的对应目录是空的,mount会将外部的目录覆盖容器内部目录,也就是说内部目录的数据也会被清空。如果外部目录有文件,也被复制进去,而且内部原有的文件会被清空。相当于两种挂载方式处理文件是相反的,一种是把内部的复制到外部,一种是把外部的文件复制到内部,可以根据不同的需求选择不同的挂载方式。 tn5>mount方式会将外部的目录覆盖容器内部目录,内部的文件会被清空。不管外部目录有没有文件内部目录的文件都会被清空,如果外部有文件就被外部的文件给复制出来。所以如果是把容器的内部的文件映射出来在外部使用,更推荐使用Volumes方式,但是如果镜像会经常更新,而以前持久化的数据存储在外边,如果使用Volumes方式新打包的镜像启动容器就会覆盖以前的内容,所以需要根据实际情况选择挂载方式。 **视频地址:** 链接: https://pan.baidu.com/s/1Z8PoO9sHIx8pTPlZkTT0hA?pwd=26y6 提取码: 26y6 复制这段内容后打开百度网盘手机App,操作更方便哦