docker容器实现数据持久化的两种方式及其区别

前言

这篇博文是我对docker实现数据持久化几种方式的特征进行一个总结。

在docker中,它的存储文件系统是在dockerhost上原有的xfs或ext4架设了一层文件系统:overlay2(将此行重点标注的原因就是我在面试中被问到过:docker使用的是什么文件系统?),通过docker info命令可以查看出主机上docker相关的信息,包括支持的网络类型、系统版本、内核版本、docker主机的cpu、内存等信息。如下:

在docker中实现数据持久化有两种方式:Bind mount和Docker Manager Volume。

Bind mount和Docker Manager Volume的区别:

  • Bind mount数据持久化的方式,如果是挂载本地的一个目录,则容器内对应的目录下的内容会被本地的目录覆盖掉,而Docker Manager Volume这种方式则不会,不管哪种方式的持久化,在容器被销毁后,本地的数据都不会丢失。
  • 使用“-v”选项挂载时,Bind mount明确指定了要挂载docker host本地的某个目录到容器中,而Docker Manager Volume则只指定了要对容器内的某个目录进行挂载,而挂载的是docker host本地的哪个目录,则是由docker来管理的。

数据持久化的特点:

  • Data Volume是目录或文件,不能是没有格式化的磁盘(块设备)。
  • 若要挂载一个文件到容器中,那么该文件必须是已经存在,否则,会被当成一个目录挂载到容器中。
  • 默认挂载到容器内的文件或目录,容器是有读写权限。可以在运行容器时-v指定完挂载目录后面加“:ro” 限制容器的写入权限(:ro来限制)。
  • volume数据可以永久保存,即使使用它的容器已经被销毁。

1、Bind mount——数据卷容器:--volumes-from方式实现数据持久化

以下数据卷容器挂载的方式就是Bind mount实现方式。

实现的大概思路如下:

  1. 运行一个容器作为数据卷容器,挂载本地目录到容器内的本地目录,无需所挂载的源目录或目标挂载点是否存在,docker会自动创建相应的目录的,也无需考虑使用哪个镜像来运行这个容器,任意镜像都可以;
  2. 之后无论运行多少容器,都可以使用--volumes-from选项来指定第一个运行的容器进行数据持久化;
  3. 实现的效果为:挂载数据卷容器实现数据持久化的容器,会自动将数据卷容器挂载的本地目录挂载到该容器本身(本身的挂载点与数据卷容器的挂载点自动保持一致),也仅仅只会挂载数据卷容器实现了数据持久化的目录到自己本身,而不是数据卷容器的全部目录。

上面实现的效果可能我表达的不够好,举个例子 :
有A、B、C这三个容器,其中A作为数据卷容器,挂载了本地的/data/web01和/data/web02这两个目录到容器内的/usr/share/nginx/html/和/data这两个目录。
容器B和容器C在运行之初,通过--volumes-from选项来指定容器A的名称或ID,那么最终实现的效果就是,A、B、C这三个容器内都会存在/usr/share/nginx/html及/data这两个目录,并且是实现了数据持久化的,对应的本地目录都是/data/web01和/data/web02。

#基于busybox镜像来做数据卷容器
[[email protected] ~]# docker run -tid --name data -v /data/web01/:/dbdata -v /data/web02:/index busybox
#运行两个nginx容器
[[email protected] ~]# docker run -d --name web01 --volumes-from data -P nginx
[[email protected] ~]# docker run -d --name web02 --volumes-from data -P nginx

当容器运行成功后,通过命令docker inspect 容器名称来查看容器的挂载信息(在查看出来的信息中找到mount字段):

1)数据卷容器data查看到的mount信息如下:

[[email protected] ~]# docker inspect data

2)容器web01查看到的mount信息如下:

[[email protected] ~]# docker inspect web01

3)容器web02查看到的mount信息如下:

[[email protected] ~]# docker inspect web02

不难发现,采用数据卷容器这种方式可以让多个容器挂载相同的目录,让其要实现数据持久化的目录保持一致。

在需要运行的容器都运行完成后,--volumes-from指定的容器,停止或被删除,都不会影响基于nginx镜像运行的容器数据持久化。

数据卷容器使用场景:

  • 多个容器需要实现数据持久化的目录是一致的,可以采用这种方式。
  • 如果不使用这种方式,并且还要对多个目录实现数据持久化,那么每运行个容器都要指定很多"-v"选项来指定目录,并且出现指定错误的几率比较大。

2、Docker Manager Volume实现数据持久化

#运行容器时,-v选项只指定一个路径,则就是容器内的目录,也就是Docker Manager Volume方式
[[email protected] ~]# docker run -tid -v /usr/share/nginx/html -P --name web03 nginx
[[email protected] ~]# docker inspect web03   #查看容器的mount字段信息

返回的信息如下:

可以看到,它是挂载的本地一个目录,这个目录看起来比较杂乱无章,其实不然,它是docker 的root根目录,在其根目录下有一个volume目录,这个目录就是用来存放Docker Manager Volume实现数据持久化产生的数据的,在volume目录下会有以容器ID命名的目录,然后下面会有_data这个目录,这个目录就是和容器内的数据持久化目录遥相对应的。建议了解一下docker 的根目录下都有哪些东西,面试的时候我被问到过。根目录下的部分信息如下:

———————— 本文至此结束,感谢阅读 ————————

原文地址:https://blog.51cto.com/14154700/2463582

时间: 2024-07-30 02:32:31

docker容器实现数据持久化的两种方式及其区别的相关文章

内存数据持久化的两种常见方法

内存数据持久化的两种常见方法: 1.将内存数据定期dump到磁盘 优点:效率高,操作简便 缺点:会损失部分数据 2.利用类似于mysql的binlog日志的方式,记录更新操作,需要时回放数据 优点:可保证数据完整性 缺点:会损失部分性能,实现稍微复杂点 redis实现了这两种方式

数据持久化的一种方式

/** *数据持久化的四种方式 * *1-------属性列表 * *2-------对象归档 * *3-------SQLite3 * *4-------Core Data * *下面是数据持久化的第一种方式-----写入文件 */ /** *写入文件思路 * *1-----获取需要写入的文件对象 * *2-----获取需要写入的文件对象的文件路径 * *3-----写入文件 * *4-----读取文件 */ NSString* string=@"Copyright (c) 2015年 妖精的

QF——iOS中数据持久化的几种方式

数据持久化的几种方式: 一.属性列表文件: .plist文件是种XML文件.数组,字典都可以和它互相转换. 读取plist文件生成数组:plist——>NSArray 把数组写入plist文件:NSArray——>plist 二.NSUserDefaults: 它是单例的.通过[NSUserDefaults standardUserDefaults];提供唯一的实例 NSUserDefaults存储数据,本质上就是属性列表plist文件里.只不过是系统提供的,存储位置固定的,它存储在沙盒的Li

redis持久化的两种方式

Redis的所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上(这称为"半持久化模式"):也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为"全持久化模式"). 由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能,将数据保存到磁盘上,当redis重启后,可以从磁盘中恢复数据.redis提供两种方式进行持久化,一种是RDB持久化(原理是将Reids

JAVA中创建字符串的两种方式的区别

我们知道,通常在Java中创建一个字符串会有两种方式,通过双引号直接赋值和通过构造器来创建. String x = "abcd"; String y = new String("abcd"); 然而,这两种方式之间的区别是什么?分别应用于哪些情况,之前还不是很懂. 1.双引号的方式 String x = "abcd"; String y = "abcd"; System.out.println(x==y);//true Sys

Java并发编程-创建线程的两种方式及区别

转载请注明:http://blog.csdn.net/UniKylin/article/details/45016117 1.线程和进程的区别 并行:是多个任务在同一时间同时执行,例如多核计算机同时计算的任务可以理解为并行 并发:从微观上看是多个任务抢占一个CPU从而执行自己的任务,轮流执行任务,但是如果遇到资源冲突的时候并没有从根本提高执行效率.但是提高了CPU的使用效率. 前段时间在GitHub上的一幅图可以很好的阐述上面的概念非常形象 2.Java中创建线程的两种方式 1.第一种方式:直接

vue 路由传参 params 与 query两种方式的区别

初学vue的时候,不知道如何在方法中跳转界面并传参,百度过后,了解到两种方式,params 与 query.然后,错误就这么来了:  router文件下index.js里面,是这么定义路由的: { path:"/detail", name:"detail", component:home } 我想用params来传参,是这么写的,嗯~ this.$router.push({ path:"/detail", params:{ name:'nameV

IOS数据持久化的4种方式

9.1 数据持久化概述 9.2 iOS应用程序目录结构 9.3 读写属性列表 9.4 对象归档 9.5 访问SQLite 9.1 数据持久化概述 iOS中可以有四种持久化数据的方式: 属性列表.对象归档.SQLite3和Core Data 9.2 iOS应用程序目录结构 iOS应用程序运行在Mac os模拟器时候,有一下临时目录模拟器3.1.3为例子: /Users/tony/Library/Application Support/iPhone Simulator/3.1.3/Applicati

redis 持久化的两种方式

一:快照模式 或许在用Redis之初的时候,就听说过redis有两种持久化模式,第一种是SNAPSHOTTING模式,还是一种是AOF模式,而且在实战场景下用的最多的 莫过于SNAPSHOTTING模式,这个不需要反驳吧,而且你可能还知道,使用SNAPSHOTTING模式,需要在redis.conf中设置配置参数,比如下面这样: # Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if b