第七章-Docker存储卷

1. Docker Volume引入

参考:比特就业课

1.1 什么是存储卷?

存储卷就是将宿主机的本地文件系统中存在的某个目录直接与容器内部的文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上与此容器建立了绑定关系的目录。在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。卷的本质是文件或者目录,它可以绕过默认的联合文件系统,直接以文件或目录的形式存在于宿主机上。

宿主机的/data/web 目录与容器中的/container/data/web 目录绑定关系,然后容器中的进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿主机的文件系统建立关联关系,使得可以在宿主机和容器内共享数据库内容,让容器直接访问宿主机中的内容,也可以宿主机向容器写入内容,容器和宿主机的数据读写是同步的。

1.2 为什么需要存储卷

1.2.1 数据丢失问题

容器按照业务类型,总体可以分为两类:

显然,容器更擅长无状态应用。因为未持久化数据的容器根目录的生命周期与容器的生命周期一样,容器文件系统的本质是在镜像层上面创建的读写层,运行中的容器对任何文件的修改都存在于该读写层,当容器被删除时,容器中的读写层也会随之消失。虽然容器希望所有的业务都尽量保持无状态,这样容器就可以开箱即用,并且可以任意调度,但实际业务总是有各种需要数据持久化的场景,比如 MySQL、Kafka 等有状态的业务。因此为了解决有状态业务的需求,Docker 提出了卷(Volume)的概念。

1.2.2 性能问题

UnionFS 对于修改删除等,一般效率非常低,如果对一于 I/O 要求比较高的应用,如redis 在实现持化存储时,是在底层存储时的性能要求比较高。

1.2.3 宿主机和容器互访不方便

宿主机访问容器,或者容器访问要通过docker cp来完成,应用很难操作

1.2.4 容器和容器共享不方便

2. 存储卷分类

目前 Docker 提供了三种方式将数据从宿主机挂载到容器中

3. 管理卷 Volume

3.1 Volume 命令清单

命令功能
docker volume create创建存储卷
docker volume inspect显示存储卷详细信息
docker volume ls列出存储卷
docker volume prune清理所有无用数据卷
docker volume rm删除卷、使用中的无法删除

3.2 docker volume create

关键参数

直接不给任何参数,就是系统给的随机名字。

当然我们也可以查看他挂载到宿主机的哪一个目录。

创建一个有名字的。

3.3 docker volume inspect

参数

3.4 docker volume ls

参数。

3.5 docker volume rm

参数。

3.6 docker volume prune

清理不使用的本地卷。

参数。

3.7 管理卷创建方式二 -v参数和--mount参数

-v 和-mount 都可以完成管理卷的创建

3.7.1 -v参数

功能:完成目录映射

参数

实操。

现在我们进入这个容器,尝试把这个容器删除,看看现象是怎么样的。

如果带上-ro选项呢?(read only)

此时,已经删不了了。

3.7.2 --mount参数

完成目录的映射。

参数。

实操。

3.8 Dockerfile匿名卷

通过 Dockerfile 的 VOLUME 可以创建 docker管理卷。这个我们后续在 Dockerfile中详细讲解。我们也可以通过 dockerfile 的 VOLUME 指令在镜像中创建 Data Volume,这样只要通过该镜像创建的容器都会存在挂载点,但值得注意的是通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,而是由 docker 随机生成的。

3.9 操作案例

3.9.1 案例一

如果在宿主机对容器里面的内容作修改,会怎么样?会同步到容器中。

先把环境准备好。

改一下。

发现容器里面也同步修改了。

3.9.2 案例二

如果通过ro的方式绑定,还能修改吗?宿主机能修改吗?容器里能修改吗?

先把容器跑起来

发现宿主机上上可以改的。

发现容器里面是改不了的。

3.9.3 案例三

--mount的方式,重复上面两个案例的操作,看看能不能容器和宿主机同步。

--mount来启动一个容器。

对首页作修改。

可以修改。

3.10 docker卷的生命周期

结论:容器删除掉,卷里面的内容还是在的,毕竟这个卷本来就是用来保护数据的。

但是如果docker volume rm test3东西就肯定不在了。

3.11 卷共享

启动三个容器,绑定到同一个卷上,看看修改后会怎么样。

结论:三个容器会同时刷新。

这里就不做演示了,云服务器不想开这么多端口。

4.绑定卷 bind mount

-v 和-mount 都可以完成绑定卷的创建。

4.1 -v参数创建绑定卷

参数

第一个参数如果是宿主机的目录,那就是绑定卷,不指定,就是管理卷的匿名卷,如果是一个名称,就是管理卷。

实操

宿主机做一个修改。

发现里面也会有的。

4.2 --mount参数创建绑定卷

参数。

看下容器里面写一个文件,看看宿主机里面会不会出现。

4.3 绑定卷的操作案例

4.3.1 案例一

使用--mount方式创建容器: 创建 nginx 容器,并将宿主机/webapp1目录挂载至容器/usr/share/nginx/html目录,注意如果webapp1目录不存在会启动报错。

如果宿主机的目录不存在,会直接报错的!

4.3.2 案例二:绑定卷的共享

结论:和管理卷的共享是一样的,宿主机改了,所有容器都会修改。

5. 临时卷 tmpfs

临时卷数据位于内存中,在容器和宿主机之外。

tmpfs局限性

5.1 创建卷

方式一:指定--tmpfs创建

此时的实验和前面的都一样,但是如果容器停止了,东西就会没了。

6. 综合实战-MySQL灾难恢复

实战目的:

掌握挂载卷的使用,将 mysql 的业务数据存储到外部

实战步骤:

使用 MySQL 5.7 的镜像创建容器并创建一个普通数据卷 mysql-data 用来保存容器中产生的数据。需要在容器中连接 MySQL 服务, 并创建数据库 test, 并在在该数据库中创建一个简单的表并插入一些数据进来。

首先先找到一个mysql点容器并运行起来先。

连上这个mysql

创建一个数据库。

创建表。

删除这个正在运行的容器。

现在跑一个新的容器,绑定到原来的目录,看看东西还在不在。

发现东西还在。