zoukankan      html  css  js  c++  java
  • Docker的持久化存储和数据共享

    docker持久化数据的方案

    默认情况下,container内部新创建文件或者修改文件,结果会保存在container的可读写层中,这意味着:

    当container消失时,与container一体的可读写层也一并消失,数据并没有持久化。并且,当一个container需要其它container中可读写层的数据时,取出操作非常困难。

    container的可读写层与宿主机的文件系统紧密结合,很难将它从一台宿主机迁移到其它宿主机。

    container的可读写层,低下需要一个实现联合文件系统的storage driver,与直接在宿主机文件系统中读写数据相比效率要低。

    如果打算将数据持久化在宿主机的文件系统中,docker提供至少两个选项:volumes与bind mounts,如果docker运行在Linux操作系统中,还可以使用tmpfs .mount。

    选择正确的mount类型

    无论你选择那种mount类型,从container内部看没有区别,它们都是目录或者文件。数据都是寄存在宿主机上,只不过具体位置有所区别,如下图:

     bind mount:将宿主机中的文件、目录mount到容器上。其上的数据可以被宿主机读写,可以被mount它的所有容器读写。

    volume:volume由docker管理,比如创建、删除什么的。默认情况下,volume的存储空间来自于宿主机文件系统中的某个目录,如/var/lib/docker/volumes/,docker系统这外的程序不应该修改其中的数据。volume是官方推荐的持久化方案。

    tmpfs mount:tmpfs类型文件与普通文件的区别是只存在于宿主机内存中,不会持久化。

    有关挂载类型的更多详细信息

    volumes:由docker负责创建、管理。用户可以显式的调用命令docker volume create创建volume,也可以通过container、service的启动隐式创建。

    默认情况下创建的volume本质上还是宿主机文件系统中的一个目录,与普通目录无本质区别。一个volume可以同时供多个container使用,如果没有container使用volume,它不会自动删除,用户需运行docker volume prune明确删除它。

    如果用户显式创建volume则需要给它指定一个名称,如果是隐式创建volume则docker会自动为它分配一个在宿主机范围内唯一的名字。

    通过使用第三方提供的volume driver,用户可以将数据持久到远程主机或者云存储中,也就是说存储空间可以不由宿主机提供。

    bind mount:本质上是宿主机、container之间共享宿主机文件系统。这种持久化方法更导致container与宿主机的耦合过于紧密,所以不推荐使用。

    tmpfs mount:有特定的应用场景。比如docker可将用户名与密码等敏感数据保存在某个数据库中,当启动需要访问这些敏感数据的container或者service时,docker会在宿主机上创建一个tmpfs,然后将敏感数据从数据库读出写到tmpfs中,再将tmpfs mount到container中,安样能保证数据安全。当容器停止运行时,则相应的tmpfs也从系统中删除。

    在创建容器时,bind mount与volume两种方式使用的选项相同,都是-v或者--volume,而实际上在语法上有明显的区别。tmpfs通过--tmpfs选项实现。总之在旧版本的docker中,这一块的语法有点混乱,从docker17.0.6开始,推荐使用新选项--mount,它要清晰的多。

    volume适用场景

    • 多个容器这间共享数据
    • 宿主机不保证存在固定的目录结构
    • 持久化数据到远程主机或者云存储而非本地
    • 需要备份、迁移、合并数据时。停止container,将volume整体复制,用于备份、迁移、合并等。

    bind mount适用场景

    container共享宿主机配置文件。比如docker会将宿主机文件/etc/resov.conf文件bind mount到容器上,两者会使用相同的DNS服务器。

    开发环境中宿主机与container之间共享源代码、构建构件等。比如将整个build过程container化,将宿主机上的源代码文件夹bind mount到build container中。修改代码后,运行build container的build命令,build container则将build结构写入另一个bind mount的文件夹中。

    一些监控类container,通过读取宿主机固定文件中的数据实现监控等。

    使用bind mount与volume的提示

    如果将空volume挂载到container上的某个目录,此目录下原来的文件与子目录会复制到空volume中。

    如果bind mount一个非空目录或者文件,或者非空volume,则container目录中的原始内容将被遮蔽,当解决挂载时则自动恢复。

    eg:1 

    创建mysql1容器,在启动的时候给volume设置别名

    [root@docker ~]# sudo docker run -d -v mysql:/var/lib/mysql --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql
    [root@docker ~]# docker volume ls
    DRIVER              VOLUME NAME
    local               mysql
    [root@docker ~]# docker volume inspect mysql
    [
        {
            "CreatedAt": "2018-06-07T09:30:33Z",
            "Driver": "local",
            "Labels": null,
            "Mountpoint": "/var/lib/docker/volumes/mysql/_data",
            "Name": "mysql",
            "Options": null,
            "Scope": "local"
        }
    ]
    [root@docker ~]# 

    这种方式volume中的数据并不会因为容器的删除而消失,实现了数据持久化的目标。但是这种方式的volume需要在Dockerfile中使用VOLUME来预先指定容器中的数据存放路径。

    Bind Mounting

    Bind Mounting跟上面的方式不一样,可以动态的指定容器内文件存放路径和宿主机上的数据库卷目录。

    采用Bind Mounting的方式实现volume的话,容器内外的数据是同步的,只需要修改一个地方,容器内或者容器外都会同步修改,非常的方便快捷。

      采用Bind Mounting的方式,将docker作为开发环境可以使我们的开发环境和生产环境保持一致,这也是实现DevOps的第一步。(很多开发使用的都是Windows的系统,但是服务器一般都是Linux的,无法保持环境的一致性,影响开发效率。)

    默认情况下,container内部新创建文件或者修改文件,结果会保存在container的可读写层中,这意味着:
    当container消失时,与container一体的可读写层也一并消失,数据并没有持久化。并且,当一个container需要其它container中可读写层的数据时,取出操作非常困难。container的可读写层与宿主机的文件系统紧密结合,很难将它从一台宿主机迁移到其它宿主机。container的可读写层,低下需要一个实现联合文件系统的storage driver,与直接在宿主机文件系统中读写数据相比效率要低。如果打算将数据持久化在宿主机的文件系统中,docker提供至少两个选项:volumes与bind mounts,如果docker运行在Linux操作系统中,还可以使用tmpfs .mount。————————————————版权声明:本文为CSDN博主「五星上炕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/dkfajsldfsdfsd/article/details/88789360

  • 相关阅读:
    hdu 4135 Co-prime (容斥定理)
    hdu 1509 Windows Message Queue (优先队列)
    poj 2104 K-th Number (划分树)
    hdu 1556 Color the ball (树状数组)
    海量大数据大屏分析展示一步到位:DataWorks数据服务对接DataV最佳实践
    使用MaxCompute Java SDK运行安全相关命令
    使用MaxCompute Java SDK 执行任务卡住了,怎么办?
    老代码多=过度耦合=if else?阿里巴巴工程师这样捋直老代码
    日志服务Python消费组实战(三):实时跨域监测多日志库数据
    如何限制用户仅通过HTTPS方式访问OSS?
  • 原文地址:https://www.cnblogs.com/sunlong88/p/15020961.html
Copyright © 2011-2022 走看看