容器 - 数据存储(7)

一. 基本说明

    是时候了解Docker如何管理数据了。本节主要说明持久化和非持久化,着重持久化

    数据存储分为两类,持久化和非持久化。

        ● 持久化数据是需要保存的数据,例如客户的信息、财务、审计日志等

        ● 非持久化数据是不需要保存的数据

    每个Docker容器都有自己的非持久化存储,非持久化存储自动创建,从属于容器,生命周期与容器相同。这意味着删除容器也会删除全部非持久化数据。简要说服务应用删除、重启后数据丢失,一般在内存缓存中的数据在服务重启后会丢失

    如果需要自己的容器数据保留下来,则需要将数据存储在卷上。卷与容器是解耦的,从而可以独立的创建并管理卷,并且卷并未与任何容器生命周期绑定。简要说就是把服务应用删除、停止、重启后历史的数据还会存在,以文件形式存储在磁盘上

        ● 非持久化数据是在容器内部应用的缓存中,与容器生命周期为一体

        ● 非持久化数据与容器是相互隔离状态,不随容器状态的改变而改变

二. 数据持久化实现方式

    ● volume

        docker自身管理的一种数据持久化方式

    ● mount bind

        数据由人为自定义管理的一种方式

    下面将对2钟持久化做一个演示

三. 演示镜像模板

FROM nginx

MAINTAINER wangtianciEXPOSE 80
# 创建测试镜像
docker build -f /root/nginx_dockerfile -t nginx:v1 .

四. volume持久化

    1. 如何去查看容器的存储路径

        Docker自身提供了"docker volume ls"的指令查看数据卷

[root@doc03 Docker]# docker volume ls
DRIVER              VOLUME NAME
local               2f68c77fb5b576bdb94857f113e7e5d12be7faaecd752a1ce31317655d809028
local               50d1bb27a79fd743b3b69f4be90d21f4a717b34ff5a3b2017493bbf0abeddd2b
local               58441bc7713392eb3c6895ba2aae7e26b03f325ff366a1bde3ee51b0b6f45d1c

        第二列"VOLUME NAME"为数据存储目录名称,第一眼看很懵,数据存储对应的是那个容器?如果数据量过小可以使用"find"指令去查到关键文件从而获得容器数据存储路径,当数据量过大时使用"find"不太现实

    2. 如何去自定义容器的存储路径

        Docker提供了"-v"参数来自定义容器卷名称,示范如下

[root@doc03 ~]# docker run -d --name nginx-volume-test1 -p 8888:80 -v test-volume:/usr/share/nginx/html nginx:v1
961213c2f96cca344afabf01c7579184e9edaff9a7d36b667e86a722da49eee2
[root@doc03 Docker]# docker volume ls
DRIVER              VOLUME NAME
local               2f68c77fb5b576bdb94857f113e7e5d12be7faaecd752a1ce31317655d809028
local               50d1bb27a79fd743b3b69f4be90d21f4a717b34ff5a3b2017493bbf0abeddd2b
local               58441bc7713392eb3c6895ba2aae7e26b03f325ff366a1bde3ee51b0b6f45d1c
local               test-volume
[root@doc03 ~]# tree /opt/app/Docker/volumes/test-volume
/opt/app/Docker/volumes/test-volume
└── _data
    ├── 50x.html
    └── index.html

1 directory, 2 files

        可以看到,在"volumes"目录下,docker自身创建了"test_volume/_data"目录,并且nginx主页文件"index.html"、"50x.html"也在这个目录下。说明容器内的文件会自动迁移到主机数据存储目录中

        -v:host_dirname:container_dirname

            注意:host_dirname 不需要写绝对路径,只需指明单独一个目录即可,会将数据统一存储在docker自身的数据管理目录下

        这里数据存储路径命名得有规范性,若是随意命名有可能导致环境混乱,笔者建议按照服务的名称或者是提供业务去命名

    3. 数据卷共享

        创建一个实例"nginx-volume-test1"

[root@doc03 ~]# docker run -d --name nginx-volume-test2 -p 9999:80 -v test-volume:/usr/share/nginx/html nginx:v1
3febe889c87382f1718ef3990d86cd61b59668493f9f5e8d91d6cdba26695691
[root@doc03 ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
3febe889c873        nginx:v1            "/docker-entrypoint.…"   6 seconds ago       Up 5 seconds        0.0.0.0:9999->80/tcp   nginx-volume-test2
961213c2f96c        nginx:v1            "/docker-entrypoint.…"   17 seconds ago      Up 17 seconds       0.0.0.0:8888->80/tcp   nginx-volume-test1

          在本地创建一个"test.html"的文件并访问

echo "nginx data volume test" > test.html && chmod 644 test.html

# 本地请求
[root@doc03 _data]# curl 10.125.7.74:9999/test.html
nginx data volume test
[root@doc03 _data]# curl 10.125.7.74:8888/test.html
nginx data volume test

        注意:这里得注意文件权限644

    4. 数据卷持久化

        删除实例"nginx-volume-test2"

[root@doc03 ~]# docker stop nginx-volume-test2
nginx-volume-test2
[root@doc03 ~]# docker rm nginx-volume-test2
nginx-volume-test3
[root@doc03 ~]# tree /opt/app/Docker/volumes/test-volume
/opt/app/Docker/volumes/test-volume
└── _data
    ├── 50x.html
    └── index.html
    └── test.html

        查看"test-volume"数据目录,文件并未被删除

        注意:这里得说明下"/opt/app/Docker/volumes/metadata.db"这个文件,metadata.db,存储路径的元数据并不是动态更新修改,当目录已经创建并关联的容器删除时,其他新建的容器无法使用已经创建过的这个目录,需要手动删除历史使用过的目录,可使用"docker volume --help"查看具体使用方式

五. mount bind持久化

    与"volume"不同的是,此方式用户可以自定义数据挂载路径

    docker run -d -v host_path:container_path ······

    1. 自定义数据存储路径

[root@doc03 Docker]# pwd
/opt/app/Docker
[root@doc03 Docker]# tree Container_data/
Container_data/
0 directories, 0 files

    2. 实例化一个容器    

[root@doc03 Docker]# docker run -d --name nginx-volume-test10 -p 33333:80 -v //opt/app/Docker/Container_data/nginx-volume-test10:/usr/share/nginx/html nginx:v1
2b2a7e4b05b4d0bdefa9f4b6ad32c40a7beadbcbca216bac42103518b97b427b
[root@doc03 Docker]# tree Container_data/
Container_data/
└── nginx-volume-test10

1 directory, 0 files
[root@doc03 Docker]# tree Container_data/nginx-volume-test10/
Container_data/nginx-volume-test10/

        "nginx-volume-test10"数据存储目录自动创建,且目录下不存在nginx主页文件"50x.html"、"index.html"

    3. 多容器数据卷共享

        创建一个nginx-volume-test11的实例,共享"nginx-volume-test10"文件系统

        在这里可以使用"inspect"去核查2个容器之间数据目录是否共享

[root@doc03 Docker]# pwd
/opt/app/Docker
# "nginx-volume-test11"使用了"ro"只读模式
[root@doc03 Docker]# docker run -d --name nginx-volume-test11 -p 44444:80 -v /opt/app/Docker/Container_data/nginx-volume-test10:/usr/share/nginx/html:ro nginx:v1
ca310b2e5076a7340aaa43e1a7737306ce53ffb7dd8d14f90114b3156e467106

        在宿主机上创建访问主页

[root@doc03 Docker]# echo "volume shard test" > Container_data/nginx-volume-test10/index.html
[root@doc03 Docker]# chmod 644 Container_data/nginx-volume-test10/index.html

        进入"nginx-volume-test10"并追加"test10"内容,通过"nginx-volume-test10"、"nginx-volume-test11"访问主页

[root@doc03 Docker]# docker exec -it nginx-volume-test10 /bin/bash
root@2b2a7e4b05b4:/# cd /usr/share/nginx/html/
root@2b2a7e4b05b4:/usr/share/nginx/html# ls
index.html
root@2b2a7e4b05b4:/usr/share/nginx/html# echo "test10 add content" >> index.html 
root@2b2a7e4b05b4:/usr/share/nginx/html# cat index.html
root@2b2a7e4b05b4:/usr/share/nginx/html# exit
exit
[root@doc03 Docker]# curl http://10.125.7.74:33333
volume shard test
test10 add content
[root@doc03 Docker]# curl http://10.125.7.74:44444
volume shard test
test10 add content

        进入"nginx-volume-test11"尝试追加内容

[root@doc03 Docker]# docker exec -it nginx-volume-test11 /bin/bash
root@ca310b2e5076:/# cd /usr/share/nginx/html/
root@ca310b2e5076:/usr/share/nginx/html# echo 1 > index.html 
bash: index.html: Read-only file system

        "nginx-volume-test10"、"nginx-volume-test11"测试说明数据已经共享,但是"nginx-volume-test11"由于设置了"ro"只读权限,没有权限做增删改操作,如果在主机上删除文件,则2个容器的数据也会删除

    4. 多容器数据继承

        指令模型: docker run -itd --name 子容器名称 --volumes-from  父容器名称 镜像名称 /bin/bash

        创建"nginx-volume-test20"实例

[root@doc03 Docker]# docker run -d --name nginx-volume-test20 -p 60000:80 -v //opt/app/Docker/Container_data/nginx-volume-test20:/usr/share/nginx/html nginx:v1
cda5bd44e77c979ddede127322fca7d5a0abe4997be78a4a8973b0700bceb81d

        以"nginx-volume-test20" 实例为父容器,创建"nginx-volume-test20.1"子容器

[root@doc03 Docker]# docker run -d --name nginx-volume-test20.1 --volumes-from nginx-volume-test20 nginx:v1
96df84470069a6cb59a1ba160ffd74b1fc0c91f11e60eae9f6d6544a90bf742f

        以"nginx-volume-test20.1" 实例为父容器,创建"nginx-volume-test20.1.1"子容器  

[root@doc03 Docker]# docker run -d --name nginx-volume-test20.1.1 --volumes-from nginx-volume-test20.1 nginx:v1
4224e166eade5b8348736d31d9f9e3146630bfa92772aea78522a6a323075ec5

        nginx-volume-test20.1 继承 nginx-volume-test20、nginx-volume-test20.1.1 继承 nginx-volume-test20.1,继承方自动创建目录

多容器数据场景使用的不多,这里不做过多的演示,只说明个人结论

            ● 父子容器磁盘共享,所有容器均可对容器卷做读写操作

            ● 删除父子容器中的某个节点,不会对数据造成损坏、丢失

六. volume、mount bind2者的特点

    1. volume

        ● 数据存储路径由docker程序自身管理

        ● container 内部目录数据统一在 "$volumes/_data"路径下

        ● container内数据有文件,则会统一同步至 "$volumes/_data"路径下

        ● 多个container 使用相同的 "$volumes/_data"时,所有数据共享

        ● 即使容器被销毁,数据也不会丢失

        ● 当本地路径不存在时,会自动创建

        ● 权限控制,当有多个容器共享统一数据时,可以针对部分容器目录只有只读权限(不做演示,test-volume3:/usr/share/nginx/html:ro),此限制只针对容器

        ● 实例可移植性强,数据存储路径有docker自身管理

        ● -v参数定义的名称必定是目录,不可能是文件

    2. bind mount

        ● 数据存储路径由用户自身去定义

        ● container内部有数据文件时,不会迁移至数据存储目录

        ● 多个container 使用相同的数据存储目录时,所有数据共享

        ● 即使容器被销毁,数据也不会丢失

        ● 当本地路径不存在时,会自动创建

        ● 权限控制,当有多个容器共享统一数据时,可以针对部分容器目录只有只读权限(不做演示,test-volume3:/usr/share/nginx/html:ro),此限制只针对容器

        ● 可移植性差,因为有用户自定义的host_path参数

        ● -v 参数即可指明目录也可以指明文件,当指明文件时此文件必须存在

上一篇:HANA数据库还原错误


下一篇:Docker-03-基本使用