Docker 入门到实战 之 容器数据管理

数据主要分为两类,持久化的与非持久化的。
持久化数据是需要保存的数据。例如客户信息、财务、预定、审计日志以及某些应用日志数据。非持久化数据是不需要保存的那些数据。
两者都很重要,并且 Docker 均有对应的支持方式。
每个 Docker 容器都有自己的非持久化存储。非持久化存储自动创建,从属于容器,生命周期与容器相同。这意味着删除容器也会删除全部非持久化数据。
如果希望自己的容器数据保留下来(持久化),则需要将数据存储在卷上。卷与容器是解耦的,从而可以独立地创建并管理卷,并且卷并未与任意容器生命周期绑定。最终效果即用户可以删除一个关联了卷的容器,但是卷并不会被删除。

Docker管理数据的方式有两种:

  • 数据卷
  • 数据卷容器

一、数据卷

数据卷是一个或多个容器专门指定绕过Union File System的目录,为持续性或共享数据提供一些有用的功能:

  • 数据卷 可以在容器之间共享和重用
  • 对 数据卷 的修改会立马生效
  • 对 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

注意:数据卷 的使用,类似于 Linux 下对目录或文件进行 mount,镜像中的被指定为挂载点的目录中的文件会隐藏掉,能显示看的是挂载的 数据卷。

总体来说,用户创建卷,然后创建容器,接着将卷挂载到容器上。卷会挂载到容器文件系统的某个目录之下,任何写到该目录下的内容都会写到卷中。即使容器被删除,卷与其上面的数据仍然存在。

如下图所示,Docker 卷挂载到容器的 /code 目录。任何写入 /code 目录的数据都会保存到卷当中,并且在容器删除后依然存在。
 

Docker卷挂载到容器的/code目录


上图中,/code 目录是一个 Docker 卷。容器其他目录均使用临时的本地存储。卷与目录 /code 之间采用带箭头的虚线连接,这是为了表明卷与容器是非耦合的关系。

1、创建数据卷

使用下面的命令创建新卷。

Usage:    docker volume create [OPTIONS] [VOLUME]

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker volume create  my-vol
my-vol
[root@iZ8vbdmp7p7nu6o38oalgoZ ~]#

默认情况下,Docker 创建新卷时采用内置的 local 驱动。恰如其名,本地卷只能被所在节点的容器使用。使用 -d 参数可以指定不同的驱动。

第三方驱动可以通过插件方式接入。这些驱动提供了高级存储特性,并为 Docker 集成了外部存储系统。下图展示的就是外部存储系统被用作卷存储。驱动集成了外部存储系统到 Docker 环境当中,同时能使用其高级特性。
 

外部存储接入Docker


截止到目前为止,已经存在 25 种卷插件,涵盖了块存储、文件存储、对象存储等。

  • 块存储:相对性能更高,适用于对小块数据的随机访问负载。目前支持 Docker 卷插件的块存储例子包括 HPE 3PAR、Amazon EBS 以及 OpenStack 块存储服务(Cinder)。
  • 文件存储:包括 NFS 和 SMB 协议的系统,同样在高性能场景下表现优异。支持 Docker 卷插件的文件存储系统包括 NetApp FAS、Azure 文件存储以及 Amazon EFS。
  • 对象存储:适用于较大且长期存储的、很少变更的二进制数据存储。通常对象存储是根据内容寻址,并且性能较低。支持 Docker 卷驱动的例子包括 Amazon S3、Ceph 以及 Minio。

2、查看数据卷


现在卷已经创建成功,可以通过 docker volume ls 命令进行查看,还可以使用 docker volume inspect 命令在主机里查看指定 数据卷 的信息详情。

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker volume ls
DRIVER              VOLUME NAME
local               my-vol
[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
[root@iZ8vbdmp7p7nu6o38oalgoZ ~]#

inspect 命令输出中有几点很有意思。Driver 和 Scope 都是 local。这意味着卷使用默认 local 驱动创建,只能用于当前 Docker 主机上的容器。Mountpoint 属性说明卷位于 Docker 主机上的位置。

在本例中卷位于 Docker 主机的 /var/lib/docker/volumes/my-vol/_data 目录。

使用 local 驱动创建的卷在 Docker 主机上均有其专属目录,在 Linux 中位于 /var/lib/docker/volumes 目录下,这意味着可以在 Docker 主机文件系统中查看卷,甚至在 Docker 主机中对其进行读取数据或者写入数据操作。

3、删除数据卷

有两种方式删除 Docker 卷。

Usage:    docker volume prune [OPTIONS]

Usage:    docker volume rm [OPTIONS] VOLUME [VOLUME...]

docker volume prune 会删除未装入到某个容器或者服务的所有卷,所以谨慎使用!

docker volume rm 允许删除指定卷。两种删除命令都不能删除正在被容器或者服务使用的卷。

因为没有使用 myvol 卷,所以请通过 prune 命令进行删除。

现在已经完成创建、查看以及删除卷的操作了。上述操作均未涉及容器,这也验证了卷是独立的这一特性。

到目前,已经了解了卷的创建、列表、查看以及删除命令。此外,还可以通过在 Dockerfile 中使用 VOLUME 指令的方式部署卷。具体的格式为 VOLUME < container-mount-point。

但是,在 Dockerfile 中无法指定主机目录。这是因为主机目录通常情况下是相对主机的一个目录,意味着这个目录在不同主机间会变化,并且可能导致构建失败。如果通过 Dockerfile 指定,那么每次部署时都需要指定主机目录。

二、数据卷容器

如果你有一些持久性的数据并且想在容器间共享,或者想用在非持久性的容器上,最好的方法是创建一个数据卷容器,然后从此容器上挂载数据。

1、创建数据卷容器

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run -t -i -d -v /test --name test ubuntu:14.04 echo hello

使用--volumes-from选项在另一个容器中挂载 /test 卷。不管 test 容器是否运行,其它容器都可以挂载该容器数据卷,当然如果只是单独的数据卷是没必要运行容器的。

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run -t -i -d --volumes-from test --name test1 ubuntu:14.04 /bin/bash

添加另一个容器

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run -t -i -d --volumes-from test --name test2 ubuntu:14.04 /bin/bash

也可以继承其它挂载有 /test 卷的容器

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run -t -i -d --volumes-from test1 --name test3 ubuntu:14.04 /bin/bash

非常详细的 Docker 学习笔记

 

三、备份、恢复或迁移数据卷

备份

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run --rm --volumes-from test -v $(pwd):/backup ubuntu:14.04 tar cvf /backup/test.tar /test

tar: Removing leading `/' from member names

/test/

/test/b

/test/d

/test/c

/test/a
[root@iZ8vbdmp7p7nu6o38oalgoZ ~]#
启动一个新的容器并且从test容器中挂载卷,然后挂载当前目录到容器中为 backup,并备份 test 卷中所有的数据为 test.tar,执行完成之后删除容器--rm,此时备份就在当前的目录下,名为test.tar。
[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# ls # 宿主机当前目录下产生了 test 卷的备份文件 test.tar test.tar

恢复

你可以恢复给同一个容器或者另外的容器,新建容器并解压备份文件到新的容器数据卷

[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run -t -i -d -v /test --name test4 ubuntu:14.04 /bin/bash
[root@iZ8vbdmp7p7nu6o38oalgoZ ~]# docker run --rm --volumes-from test4 -v $(pwd):/backup ubuntu:14.04 tar xvf /backup/test.tar -C / # 恢复之前的文件到新建卷中,执行完后自动删除容器 test/ test/b test/d test/c test/a

四、删除 Volumes

Volume 只有在下列情况下才能被删除:

  • docker rm -v删除容器时添加了-v选项
  • docker run --rm运行容器时添加了--rm选项

否则,会在/var/lib/docker/vfs/dir目录中遗留很多不明目录。

五、在集群节点间共享存储

Docker 能够集成外部存储系统,使得集群间节点共享外部存储数据变得简单。例如,独立存储 LUN 或者 NFS 共享可以应用到多个 Docker 主机,因此无论容器或者服务副本运行在哪个节点上,都可以共享该存储。下图展示了位于共享存储的卷被两个 Docker 节点共享的场景。接下来这些 Docker 节点可以将共享卷应用到容器之上。
 

位于共享存储的卷被两个Docker节点共享


构建这样的环境需要外部存储系统的相关知识,并了解应用如何从共享存储读取或者写入数据。这种配置主要关注数据损坏(Data Corruption)。

基于下图,设想下面的场景:Node 1 上的容器 A 在共享卷中更新了部分数据。但是为了快速返回,数据实际写入了本地缓存而不是卷中。此时,容器 A 认为数据已经更新。但是,在 Node 1 的容器 A 将缓存数据刷新并提交到卷前,Node 2 的容器 B 更新了相同部分的数据,但是值不同,并且更新方式为直接写入卷中。

此时,两个容器均认为自己已经将数据写入卷中,但实际上只有容器 B 写入了。容器 A 会在稍后将自己的缓存数据写入缓存,覆盖了 Node 2 的容器 B 所做的一些变更。但是 Node 2 上的容器 B 对此一无所知。数据损坏就是这样发生的。

为了避免这种情况,需要在应用程序中进行控制。

猜你喜欢

转载自blog.csdn.net/Roker_966/article/details/107317298