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. kafka(一)-为什么选择kafka

    作为开发人员,我们在选择一个框架或者工具时,我们都需要考虑些什么,我们不是头脑发热,一拍脑袋就它了,我们首先要认清这个框架或工具的作用是什么,能给我们带来什么样的好处,同时也要考虑带来什么样的负面结果 ...

  2. 代码审计之CVE-2017-6920 Drupal远程代码执行漏洞学习

     1.背景介绍: CVE-2017-6920是Drupal Core的YAML解析器处理不当所导致的一个远程代码执行漏洞,影响8.x的Drupal Core. Drupal介绍:Drupal 是一个由 ...

  3. Codeforces Round #615 (Div. 3) 题解

    A - Collecting Coins 题意: 给你四个数a,b,c,d,n.问你是否能将n拆成三个数A,B,C,使得A+a=B+b=C+c. 思路: 先计算三个数的差值的绝对值abs,如果abs大 ...

  4. test api formdata

  5. 20191217HNOI 模拟赛 复活石

    题目描述: 分析: 我也不知道我在干sm,但就是没写出来2333 枚举 i 的每个质因子 j ,复杂度为n^(3/2) 为什么我会认为是n^2啊2333 然后考虑 f ( j )对g ( i )做了多 ...

  6. MATLAB2017 下载及安装教程

    全文借鉴于软件安装管家 链接: https://pan.baidu.com/s/1-X1Hg35bDG1G1AX4MnHxnA 提取码: ri88 复制这段内容后打开百度网盘手机App,操作更方便哦 ...

  7. printf 函数笔记

    函数声明 int printf (const char*, ...); 说明 <返回值> printf ("<格式化字符串>", <参数表>); ...

  8. 解决apt-get安装软件包的时候遇到E: Sub-process /usr/bin/dpkg returned an error code (1)问题

    在用apt-get安装软件包的时候遇到E: Sub-process /usr/bin/dpkg returned an error code (1)问题,解决方法如下:   cd /var/lib/d ...

  9. Basic Thought / Data Structure: 差分 Difference

    Intro: 作为查询界的\(O(1)\)王者--前缀和的亲兄弟,差分,他可是修改界的\(O(1)\)王者 Prerequisite knowledge: 前缀和 Function: 仅单次询问的区间 ...

  10. AI初探1

    一个典型的机器学习的过程,首先给出一个输入数据,我们的算法会通过一系列的过程得到一个估计的函数,这个函数有能力对没有见过的新数据给出一个新的估计,也被称为构建一个模型.就如同上面的线性回归函数. 在机 ...