持久化存储和卷间状态共享
- 存储卷的简介
- 存储卷的类型
- 宿主机和容器之间如何共享数据
- 容器之间如何共享数据
- 存储卷的生命周期
- 存储卷之间的数据管理和控制模式
1、存储卷的简介
存储卷是容器目录树上的挂载点,其中一部分主机目录树已经被挂载了。
存储卷在容器化系统设计中发挥了关键作用。
存储卷提供容器无关的数据管理方式:
数据示例根据其范围或者接入容器方式的不同分为以下几种:
数据库软件与数据库的数据
web应用程序与日志数据
web数据处理应用程序的输入和输出数据
web服务器与静态内容
产品与支持工具
存储卷可分离关注点,并为架构组件创建模块化,这种模块化设计帮助我们轻松的了解、构建、支持和重用大型系统的部件。
存储卷可以隔离应用程序和主机的关系,镜像被装载到主机,创建除一个容器。Docker 本身没有办法利用主机上的设施,如装载的网络存储,或混合光纤和固态硬盘。但有主机知识的用户可以使用存储卷及其重要性,可以在一个真实的示例中开始使用它们。
Nosql 数据库使用存储卷
通过创建已定义存储卷的单个容器开始,这被称为存储卷容器。
Docker run -d \
–volume /var/lib/cassandra/data \
–name cass-shared \
Apline echo Data Container
这里在容器中指定存储卷的挂载点。
存储卷容器将立即停止,在创建运行Cassandra新容器时,使用这个存储卷:
Docker run -d \
–volumes-from cass-shared \
–name cass1 \
Cassandra:2.2
接下来,从cassandra:2.2镜像启动容器,运行cassandra客户端工具,并连接到正在运行的服务器:
Docker run -it –rm \
–link cass1:cass \
Cassandra:2.2 cqlsh cass
现在可以从CQLSH命令行检查或修改Cassandra数据库。首先,查找一个名为docker_hello_world的键空间。
Select *
From system.schema_keyspaces
Where keyspace_name=’docker_hello_world’;
Cassandra应该返回一个空列表,这意味着改示例的数据库尚未进行修改,接下来以下命令创建键空间:
Create keyspace docker_hello_world
With replication={
‘class’:’SimpleStrategy’,
‘replication_factor’:1
};
现在,你已经修改了数据库,再发相同的查询,应该是可以看到返回结果,也可确认你的更改被数据库已接受。再次运行查找命令,这一次cassandra应该返回刚才所创建的键空间的下一个条目。如果确保已经连接并且修改了Cassandra节点,就可以退出CQLSH程序并停止客户端容器:
# leave and stop the current container
Quit
客户端容器创建时,使用–rm标志,在命令停止会被自动删除,然后通过停止和去除所创建的cassandra节点,清理改示例的第一部分。
Docker stop cass1
Docker rm -vf cass1
创建一个新的cassandra节点,连接客户端,并且查询键空间,接下来测试数据的恢复:
Docker run -d \
–volumes-from cass-shared \
–name cass2 \
Cassandra:2.2
Docker run -it –rm \
–link cass2:cass \
Cassandra:2.2 \
Cqlsh cass
Select *
From system.schema_keyspaces
Where keyspace_name=’docker_hello_world’;
最后一个命令返回单个条目,将会和前面一个容器中创建的键空间相匹配,说明了存储卷如何被用于创建持久化的系统,继续往下之前,先退出并清理:
Quit
Docker rm -vf cass2 cass-shared
2、存储卷的类型
存储卷的类型有两种。
第一种类型是绑定挂载存储卷,其使用用户提供的主机目录或文件。
第二种类型是管理存储卷,其使用由docker守护进程控制的位置,被称为docker管理空间。
绑定挂载卷
绑定挂载卷指向主机文件系统用户指定的位置。
为了便捷的分享你的工作,你可以使用docker启动web服务器,并绑定挂载你的文档地址在web服务器新容器的文档根目录上,在主目录创建一个名为example-docs的新目录。在该目录中创建一个名为index.html的文件。在这个文件中,为你的朋友写一个消息。
下面的命令将启动一个Apache HTTP服务器,你的服务器会被绑定挂载在服务器的文档根目录中:
Docker run -d –name bmweb \
-v ~/example-docs:/usr/local/apache2/htdocs \
-p 80:80 \
Httpd:latest
通过这个运行的容器,能够将web浏览器指向docker引擎运行的ip地址。能够看到创建的文件。
此外,如果想确保在Apache HTTP web服务器不能更改此卷的内容。可以通过在存储卷映射规则后追加:ro来完成。
例如:
Docker rm -vf bmweb
Docker run –name bmweb_ro \
–volume ~/example-docs:/usr/local/apache2/htdocs/:ri \
-p 80:80 \
Httpd:latest
挂载只读卷,可以避免容器内的任何进程修改该卷的内容。
测试:
Docker run –rm \
-v ~/example-docs:/testpace:ro \
Alpine \
/bin/sh -c ‘echo test > /testspace/test’
该命令试图将单词“test”添加到卷上一个名为test的文件中,但由于卷被挂载成只读卷,该命令执行失败。
还需要注意的时,如果指定了不存在的主机目录,docker会为你创建想要的目录,虽然这可以派上用场,但依靠这个功能并不是好办法,最好在这个目录上对权值设置更多的管控。
Ls ~/example-docs/absent 验证absent目录不存在
Docker run –rm -v ~/example-docs/absent:/absent alpine:latest \
/bin/sh -c ‘mount’ | grep absent’
Ls ~/example-docs/absent
绑定挂载卷并不限于目录,你还可以绑定挂载卷妆容单个文件。
使用绑定挂载卷的第一个问题是它们将可移植容器绑定到特定主机的文件系统,如果容器的定义取决于主机文件系统特定位置上的内容,无论所在的位置的内容可用或不可用,该定义无法跨主机移植。
第二个问题是,创造了与其他容器发生冲突的机会。启动cassandra的多个实例,都使用相同的主机位置挂载存储卷,这将是一个糟糕的主意,在这种情况下,每个实例将竞争相同的一组文件,如果没有其他工具,比如文件锁定,这将有可能导致数据库损坏。
docekr管理卷
执行docekr run 使用-v 选项(或–volume),只要指定容器目录树中的挂载点,管理卷即可创建。
Docker run -d \
-v /var/lib/cassandra/data \
–name cass-share \
Alpine echo data container
在创建这个容器的同时,docker守护程序在主机文件系统中创建了目录,来存储这三个存储卷的内容。
为了找到目录的确切位置,可以使用docker inspect命令过滤卷键:
Docker inspect -f “{
{json .Volumes}}” cass-shared
卷键指向这个映射的键值,在这个映射中每一个键都是容器中的挂载点,键值是主机文件系统上的目录位置。该映射对键的字典式排序,和创建容器时所指定的顺序无关。
注意:键值中指定的主机路径是相对于虚拟机的根文件系统,而不是主机的。
使用管理卷可以帮忙管理混乱。
3、共享存储卷
两种方法来共享容器之间的存储器
①主机依赖的共享
两个或多个容器使用主机依赖的共享,即每个容器在主机文件系统的已知位置有一个绑定挂载卷。
例如:
Mkdir -/web-logs-example 创建已知目录
Docker run –name plath -d \ 绑定挂载该目录为日志可写容器
-v ~/web-logs-example:/data \
Dockerinaction/ch4_writer_a
Docker run –rm \ 绑定挂载该目录为日志只读容器
-v -/web-logs-example:/reader-data \
Alpine:latest \
Head /reader-data/logA
Cat ~/web-logs-example/logA 查看容器日志
Docker stop plath 停止可写容器
容器可能以这种方式连接在一起:
启动四个容器:
两个日志写入者和两个读取者:
Docker run –name woolf -d \
–volume ~/web-logs-example:/data \
Dockerinaction/ch4_writer_a
Docker run –name alcott -d \
-v ~/web-logs-example:/data \
Dockerinaction/ch4_writer_b
Docker run –rm –entrypoint head \
-v ~/web-logs-example:/towatch:ro
Alpine:latest \
/towatch/logA
Docker run –rm \
-v ~/web-logs-example:/toread:ro \
Apline:latest \
Head /toread/logB
在这里前两个容器写入到卷的不同文件中。
第二和第四个容器则在不同的位置挂载卷,并作为只读。
②共享和volumes-form标志
Docker run 命令提供了一个标志,可将卷从一个或多个容器复制到新的容器中,标志–volumes,可设定多次,可指定多个源容器。