Docker深入浅出系列 | 容器数据持久化

Docker已经上市很多年,不是什么新鲜事物了,很多企业或者开发同学以前也不多不少有所接触,但是有实操经验的人不多,本系列教程主要偏重实战,尽量讲干货,会根据本人理解去做阐述,具体官方概念可以查阅官方教程,因为本系列教程对前一章节有一定依赖,建议先学习前面章节内容。

本系列教程导航:

Docker深入浅出系列 | 容器初体验

Docker深入浅出系列 | Image实战演练

Docker深入浅出系列 | 单节点多容器网络通信

教程目的:

  • 了解Docker怎么实现数据存储
  • 了解Docker数据挂载方式是什么
  • 了解Docker数据持久化怎么使用
  • 了解Docker不同数据挂载方式的使用场景

Docker数据存储方式



Docker容器对于宿主机器来说只是一个运行在Linux上的应用,因此它的数据存储还是会依赖宿主机器,Docker是通过挂载宿主机文件系统或内存的方式来实现数据存储的,挂载方式有三种:volume、bind mount和tmpfs。

  • volumes - 在宿主的文件系统上的docker工作路径下创建一个文件夹(/var/lib/docker/volumes)来存储数据,其他非docker进程是不能修改该路径下的文件,完全由docker来管理
  • bind mounts - 可以存储在宿主机器任何一个地方,但是会依赖宿主机器的目录结构,不能通过docker CLI 去直接管理,并且非docker进程和docker进程都可以修改该路径下的文件
  • tmpfs - 无论是在Docker主机上还是在容器内,tmpfs挂载都不会持久保存在磁盘上,它会将信息存储在宿主机器内存里。 容器在其生存期内可以使用它来存储非持久状态或敏感信息。 例如,在内部,swarm services 使用tmpfs挂载将机密挂载到服务的容器中 或者 我们一些不需要持久化数据的开发测试环境,可以使用tmpfs

Volumes初体验

Volumes 是Docker推荐的挂载方式,与把数据存储在容器的可写层相比,使用Volume可以避免增加容器的容量大小,还可以使存储的数据与容器的生命周期独立。

  • 与bind mounts相比,volumes更易于备份或迁移。
  • 您可以使用Docker CLI命令或Docker API管理Volumes。
  • volumes在Linux和Windows容器上均可工作。
  • 可以在多个容器之间更安全地共享volumes。
  • volumes驱动程序使您可以将volumes存储在远程主机或云提供程序上,以加密volumes内容或添加其他功能。

Volumes实战

通过默认-v方式

默认情况下,docker会帮我们创建一个随机命名的volume

1.利用我们前面章节下载的image,创建一个容器,命名为mysql01

[root@localhost /]# docker run -d --name mysql01 -e MYSQL_ROOT_PASSWORD=evan123 mysql
4dc868313a330840a833d78a1a88462bcfa4562f61f7da5dcecc9a57290bcb82

2.我们可以看看容器到底有没有自动帮我们创建一个volumes

[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54

通过上面的输出结果可以看到,docker 默认帮我创建了一个volume,并且随机起了一个看不懂的名字

3.通过docker inspect查看volume详细信息

[root@localhost /]# docker inspect cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54
[
{
"CreatedAt": "2020-02-26T07:39:49Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54/_data",
"Name": "cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54",
"Options": null,
"Scope": "local"
}
]

从上面volume详情可以了解到,现在容器的数据是挂在在宿主机器上 /var/lib/docker/目录下, scope是本地

4.通过-v指定容器volume的名字,使用我们自定义的一个可读的名字

[root@localhost /]# docker run -d --name mysql02 -v evan_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=evan124 mysql
4d51b14837ab8564b878043420ea923565bafe90880eaa7bf362dbc35c7f756c

5.再次查看下volume是否创建成功

[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54
local evan_volume

刚才创建的volume已经成功了

6.再查看下volume的详细信息

[root@localhost /]# docker inspect evan_volume
[
{
"CreatedAt": "2020-02-26T11:00:02Z",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/evan_volume/_data",
"Name": "evan_volume",
"Options": null,
"Scope": "local"
}
]

从上面信息可以看到,容器已经成功挂载宿主机器上的evan_volume

通过--mount方式

-v能做的--mount指令都可以做,与-v指令对比,--mount指令更灵活,支持更多复杂操作,并且不需要严格按照参数顺序,通过key value键值对方式进行配置,可读性更高。

--mount有以下几个参数:

  • type - type可以是bind、volume或者tmpfs,默认是volume
  • source - 宿主机上的目录路径,可以用缩写src
  • destination - 目标路径,容器上挂载的路径,可以用dst或者 target
  • readonly - 可选项,如果设置了,那么容器挂载的路径会被设置为只读
  • volume-opt - 可选项,当volume驱动接受同时多个参数作为选项时,可以以多个键值对的方式传入

1.创建一个容器,命名为mysql-mount,指定volume名为mysql-mount

[root@localhost /]# docker run --name mysql-mount -e MYSQL_ROOT_PASSOWRD=evan123 --mount type=volume,source=mysql-mount,target=/var/lib/mysql mysql
2020-02-26 12:09:37+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian9 started.
2020-02-26 12:09:37+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2020-02-26 12:09:37+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian9 started.
2020-02-26 12:09:37+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

2.查看volume是否创建成功

[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54
local evan_volume
local mysql-mount
local myvol2
local myvol3

从上面查询结果可以看出来,mysql-mount已经创建成功

3.查看宿主机器是否存在对应的目录

        "Mounts": [
{
"Type": "volume",
"Name": "mysql-mount",
"Source": "/var/lib/docker/volumes/mysql-mount/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
]

从输出结果可以看到,通过--mount可以实现跟-v同样的操作结果,数据也绑定宿主机器上docker路径对应目录


bind mounts初体验

与volumes相比,bind mount的功能有限。 使用绑定安装时,会将主机上的文件或目录安装到容器中。 文件或目录由主机上的完整或相对路径引用。 相比之下,当您使用volume时,将在主机上Docker的存储目录中创建一个新目录,并且Docker管理该目录的内容。

该文件或目录不需要在Docker主机上已经存在。 如果尚不存在,则按需创建。 bind mounts性能非常好,但是它们依赖于具有特定目录结构的主机文件系统。 如果要开发新的Docker应用程序,请考虑使用命名volume。 您不能使用Docker CLI命令直接管理bind mounts

1.创建一个tomcat容器,命名为tomcat-bind,挂载宿主机器路径为/tmp

[root@localhost /]# docker run -d --name tomcat-bind --mount type=bind,source=/tmp,target=/user/local tomcat
3dab7d9f469b231ff68072ff8b910e25270c1ab28a944efc0a2b0c9c321e57df

2.通过docker inspect tomcat-mount查看容器信息

        "Mounts": [
{
"Type": "bind",
"Source": "/tmp",
"Destination": "/user/local",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],

可以看到容器已经成功挂载到宿主机器上的/tmp目录,而不是前面我们演示的docker管理路径下


tmpfs初体验

使用tmpfs不会持久化数据,数据只会存放在宿主机器内存中

1.创建一个tomcat容器,命名为tomcat-tmps,指定挂载方式为temps

[root@localhost /]# docker run -d --name tomcat-tmpfs --mount type=tmpfs,target=/tmp tomcat
fdf6c8a7ae067db01ed97dc3c3a6903f615a8b687e9b06cd70218a0e8a2d6bf4

2.我们通过docker container inspect tomcat-tmpfs 查看下是否会创建任务目录在宿主机器

        "Mounts": [
{
"Type": "tmpfs",
"Source": "",
"Destination": "/tmp",
"Mode": "",
"RW": true,
"Propagation": ""
}
],

从上面输出结果可以看到,宿主机器上并没有任何目录,只是在目标路径也就是容器里指定了/tmp作为数据存储路径


验证docker数据存储

思路:我们尝试在mysql容器创建一个数据库,然后退出后把容器删除掉,再创建一个新的容器,数据存储路径指向同一个volume,观察是否在新的容器可以看到上一个容器创建好的数据库



1.进入我们上面创建的mysql

[root@localhost /]# docker exec -it mysql01 bash

2.创建数据库eshare

mysql> create database eshare
-> ;
Query OK, 1 row affected (0.00 sec) mysql> show databases;
+--------------------+
| Database |
+--------------------+
| eshare |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)

从输出结果可以看到,数据库已经创建成功

3.退出容器,删除mysyql01容器

mysql> exit
Bye
root@4dc868313a33:/# exit
exit
[root@localhost /]# docker container rm -f mysql01
mysql01

容器mysql01已经顺利删除

4.查看mysql01挂载的volume是否还在

[root@localhost /]# docker volume ls
DRIVER VOLUME NAME
local cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54
local evan_volume
local mysql-mount
local myvol2
local myvol3

可以看到,对应的volume还在

DRIVER              VOLUME NAME
local cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54

5.创建一个新mysql容器,命名为mysql-volume,并且绑定mysql01的volume

[root@localhost /]# docker run -d --name mysql-volume -v cc439258feb4817e1ecfa1f6969613f3e84be9a4499819ec7386f7e443eb6c54:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=evan123 mysql
360127340b462c3539f158c776aef03fd8f58c5a2aafdd622e0f1c161a1bd189

6.验证新的容器mysql-volume 中,是否存在已经创建好的数据库eshare

[root@localhost /]# docker exec -it mysql-volume bash
root@360127340b46:/# mysql -uroot -pevan123 mysql> show databases;
+--------------------+
| Database |
+--------------------+
| eshare |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)

从上面输出结果可以看到,新的容器已经存在之前创建好的数据库,这就证明了docker不仅可以持久化数据,并且不同容器还可以共享同一个volume。


有兴趣的朋友,欢迎加我公众号一起交流,有问题可以留言,平时工作比较忙,我也抽时间尽量回复每位朋友的留言,谢谢!

Docker深入浅出系列 | 容器数据持久化的更多相关文章

  1. Docker深入浅出系列 | 容器初体验

    目录 Docker深入浅出系列 | 容器初体验 教程目标 预备工作 容器与虚拟化技术 什么是Docker 为什么要用Docker 事例 什么是容器镜像和容器 容器与虚拟机的区别 Vagrant与Doc ...

  2. docker 系列 - 容器数据持久化和数据共享

    docker 主要有两种数据存储形式, 一种是storage driver(也叫做 Graph driver), 另一种是 volume driver. stroage driver主要是存储那些无状 ...

  3. Docker深入浅出系列 | Docker Compose多容器实战

    目录 前期准备 Docker Compose是什么 为什么要用Docker Compose Docker Compose使用场景 Docker Compose安装 Compose Yaml文件结构 C ...

  4. Docker深入浅出系列 | 单机Nginx+Springboot实战

    目录 Nginx+Springboot实战 前期准备 实战目标 实战步骤 创建Docker网络 搭建Mysql容器 搭建额度服务集群 搭建Nginx服务 验证额度服务 附录 Nginx+Springb ...

  5. Docker深入浅出系列 | Swarm多节点实战

    目录 前期准备 Swarm基本概念 什么是Docker Swarm 为什么要用Swarm Swarm的网络模型 Swarm的核心实现机制 服务发现机制 负载均衡机制Routing Mesh Docke ...

  6. Docker深入浅出系列 | 5分钟搭建你的私有镜像仓库

    Docker已经上市很多年,不是什么新鲜事物了,很多企业或者开发同学以前也不多不少有所接触,但是有实操经验的人不多,本系列教程主要偏重实战,尽量讲干货,会根据本人理解去做阐述,具体官方概念可以查阅官方 ...

  7. Docker深入浅出系列 | 单节点多容器网络通信

    目录 教程目标 准备工作 带着问题开车 同一主机两个容器如何相互通信? 怎么从服务器外访问容器 Docker的三种网络模式是什么 Docker网络通信原理 计算机网络模型回顾 Linux中的网卡 查看 ...

  8. Docker深入浅出系列 | Image实战演练

    目录 课程目标 Container与Image核心知识回顾 制作Docker Image的两种方式 Dockerfile常用指令 Image实战篇 通过Dockerfile制作Image 通过Dock ...

  9. Docker 容器数据 持久化(系统学习Docker05)

    写在前面 本来是可以将数据存储在 容器内部 的.但是存在容器内部,一旦容器被删除掉或者容器毁坏(我亲身经历的痛,当时我们的大数据平台就是运行在docker容器内,有次停电后,不管怎样容器都起不来.以前 ...

随机推荐

  1. 【模板】2-SAT问题

    问题简述 有 \(n\) 个变量,每个变量可赋为 \(1\) 或 \(0\) 必须满足一些限制条件,如" \(a\) 为1 或 \(b\) 为0 " " \(a\) 为0 ...

  2. Ubuntu下cc和gcc的关系

    在编写makefile时找到过很多例子,其中有一些用的bash是cc,而有的则是gcc,然后就去查阅了一些相关资料.原来cc是Unix下的c编译器,而gcc则是Linux下的编译器.那么问题来了,在L ...

  3. UML--->活动图梳理

    活动图梳理 活动图 概述 活动图是UML用于对系统的动态行为建模的另一种常用工具,它描述活动的顺序,展现从一个活动到另一个活动的控制流,常常用于描述业务过程和并行处理过程,活动图在本质上是一种流程图. ...

  4. Python学习,第八课 - 函数

    本次讲解函数,由于内容比较多,小编列了个大纲,主要有一下内容: 1. 函数基本语法及特性 2. 函数参数 3.局部变量 4. 返回值 5.嵌套函数 6.递归 7.匿名函数 8.高阶函数 9.内置函数 ...

  5. Docker基础内容之容器

    前言 容器是独立运行的一个或一组应用以及它们的运行态环境. 相关命令 启动容器相关命令 docker run 运行一个ubuntu14.04版本的容器,如果这个镜像本地不存在则会去默认仓库中下载 do ...

  6. Realm及相关对象(四)

    Shiro Realm 1.UserRealm 父类 AuthorizingRealm 将获取 Subject 相关信息分成两步:获取身份验证信息(doGetAuthenticationInfo)及授 ...

  7. Spring-cloud微服务实战【七】:服务熔断与降级hystrix

      在之前的文章中,我们先后介绍了eureka,ribbon,feign,使用eureka集群的方式来保证注册中心的高可用,在eureka中使用ribbon进行负载均衡,使用feign接口替换手动编码 ...

  8. <背包>solution_CF366C_Dima and Salad

    Dima and Salad Dima, Inna and Seryozha have gathered in a room. That's right, someone's got to go. T ...

  9. CAD制图系列之如何画内切圆

    今天我将记录我们如何画一个大圆,里面均匀内切四个小圆 具体步骤如下: 第一步:首先,先画一个十字架,用于作为轴 第二步:以十字架交点为圆心,画一个半径为25的圆 第三步:以中点为坐标画四十五度斜线,方 ...

  10. vscode 调试 react 项目

    主要分为以下三个步骤 安装 debug for chrome 配置 launch.json 文件 配置内容如下 { "version": "0.2.0", &q ...