容器中的数据能够存储在容器层。可是将数据存放在容器层存在如下问题:linux
- 数据不是持久化。意思是若是容器删除了,这些数据也就没了
- 主机上的其它进程不方便访问这些数据
- 对这些数据的I/O会通过存储驱动,而后到达主机,引入了一层间接层,所以性能会有所降低
Docker 提供了3种持久化数据的方式:docker
- volumes:存于主机文件系统中的某个区域,由Docker管理(/var/lib/docker/volumes/ on linux)。非Docker进程不该该修改这些数据。卷是Docker中持久化数据的最好方式
- bind mount:存于主机文件系统中的任意位置。非Docker进程能够修改这些数据
- tmpfs mount(Linux中):存于内存中(注意,并非持久化到磁盘)。在容器的生命周期中,它能被容器用来存放非持久化的状态或敏感信息

volumes安全
若是没有显式建立,一个卷会在最开始挂载时被建立。当容器中止时,卷仍然存在。多个容器能够经过read-write或read-only的方式使用同一个卷。架构
只有在显式删除时,卷才会被删除。若是将一个空卷挂载到容器中一个存有文件或目录的目录中,这些文件或目录会被拷贝到空卷中;若是将一个非空卷挂载到容器中一个存有文件或目录的目录中,这些文件或目录会被隐藏。app
使用
- 建立:docker volume create
- 删除某个卷:docker volume rm 卷名
- 删除全部未使用的卷:docker volume prune
- 列出全部卷:docker volume ls
- 查看某个卷的信息:docker volume inspect 卷名
- 挂载到容器:-v或--volume。若是是Docker17.06或更高:推荐使用--mount。(同 bind mount)
- 挂载类型:key为type,value为bind、volume或tmpfs
- 挂载源:key为source或src,对于命名卷,value为卷名,对于匿名卷,则忽略
- 容器中的挂载点:key为destination、dst或target,value为容器中的路径
- 读写类型:value为readonly,没有key
- volume-opt选项,能够出现屡次。好比volume-driver=local,volume-opt=type=nfs,…
- 第一个域:对于命名卷,为卷名;匿名卷,则忽略,此时会建立匿名卷
- 第二个域:容器中的挂载点
- 第三个域:可选参数,由','隔开,如ro
- -v或—volume:由3个域组成,’:’分隔
- —mount:由多个’,’隔开的键值对
- =组成:
当使用docker service create 启动Docker服务时,只支持--mount,不支持-v和--volume。而且每一个服务容器使用它们各自的本地卷,所以若是使用本地(local)卷驱动,容器没法经过卷共享数据,可是一些卷驱动支持共享存储。Docker for AWS和Doocker for Azure都使用Cloundstor plugin支持持久存储
场景
- 多个运行容器间共享数据
- 当Docker主机不确保具备给定的目录或文件时。卷能够将容器运行时与Docker主机的配置解耦合
- 备份、恢复、或将数据从一个Docker主机迁移到另外一个Docker主机时
bind mountssh
主机中的文件或目录经过全路径被引用。在使用绑定挂载时,这些目录或文件不必定要已经存在。性能
若是使用这种方式将一个目录挂载到容器中一个存有文件或目录的目录中,这些文件或目录会被隐藏;若是主机中的文件或目录不存在,当使用--mount挂载时,Docker会报错,当使用-v或--volume时,会在主机上建立目录ui
使用
挂载到容器:-v或—volume。若是是Docker17.06或更高:推荐使用—mount。(同 volumes)spa
- -v或--volume:由3个域组成,':'分隔
- 第一个域:对于命名卷,为卷名;匿名卷,则忽略,此时会建立匿名卷
- 第二个域:容器中的挂载点
- 第三个域:可选参数,由','隔开,如ro
- --mount:由多个','隔开的键值对<key>=<value>组成:
- 挂载类型:key为type,value为bind、volume或tmpfs
- 挂载源:key为source或src,value为主机中文件或目录的路径
- 容器中的挂载点:key为destination、dst或target,value为容器中的路径
- 读写类型:value为readonly,没有key
- bind-propagation选项:key为bind-propagation,value为rprivate、private、rshared、shared、rslave或slave
- 一致性选项:value为consistent、delegated、cached。这个选项仅仅适用于Docker for Mac
- --mount不支持z和Z(这个不一样于-v和—volume)
场景
大致上来讲,只要可能,最好使用volumes
- 主机与容器共享配置文件(Docker默认状况下经过这种方式为容器提供DNS解析,经过将/etc/resolv.conf挂载到容器中)
- 共享源代码或build artifacts(好比将Maven的target/目录挂载到容器中,每次在Docker主机中build Maven工程时,容器可以访问到那些rebuilt artifacts)
- 当 docker主机中的文件或目录结构和容器须要的一致时
bind propagation插件
对于bind mount和volumes,默认都是rprivate。只有在使用bind mount时可配置,且必须在linux下。bind propagation是个超前主题,对于大多数用户来讲,并不须要配置
对于一个挂载点/mnt,假设它同时也被挂载到/tmp。bind propagation控制 whether a mount on /tmp/a would also be available on /mnt/a

在设置bind propagation以前,主机文件系统须要支持bind propagation
下面的例子将主机中的target/挂载到容器中2次:

此时若是建立/app/foo/,/app2/foo也会存在
selinux label
你能添加z或Z选项来修改挂载到容器中的主机文件或目录的selinux label:
- z选项指明bind mount的内容在多个容器间是共享的
- Z选项指明bind mount的内容是私有不共享的
要特别当心的使用这两个选项。”Bind-mounting a system directory such as /home or /usr with the Z option renders your host machine inoperable and you may need to relabel the host machine files by hand”
tmpfs mount
只在linux中支持
相对于volumes和bind mount,tmpfs mount是临时的,只在主机内存中持久化。当容器中止,tmpfs mount会被移除。对于临时存放敏感文件颇有用
不一样于volumes和bind mount,多个容器没法共享tmpfs mount
使用
- 挂载到容器:—tmpfs。若是是Docker17.06或更高:推荐使用—mount
- 挂载类型:key为type,value为bind、volume或tmpfs
- 容器中的挂载点:key为destination、dst或target,value为容器中的路径
- tmpfs-size和tmpfs-mode选项
- —tmpfs:直接指定容器中的挂载点。不容许指定任何配置选项
- —mount:由多个’,’隔开的键值对
- =组成:

场景
- 最好的使用场景是你既不想将数据存于主机,又不想存于容器中时。这能够是出于安全的考虑,或当应用须要写大量非持久性的状态数据时为了保护容器的性能
volume drivers
机器间共享数据
当构建错误容忍应用时,可能须要配置同一个服务的多个副原本访问相同的文件:

有多种方法来实现这个目的:
- 为应用添加逻辑,将文件存储到一个云对象存储系统(如Amazon S3)中
- 使用一个支持将文件写入外部存储系统(如NFS或Amazon S3)的driver来建立卷
volume drivers能够将底层存储系统从应用逻辑中抽象出来。好比,若是你的服务使用一个具备NFS driver的卷,你能更新你的服务使用不一样的driver,做为在云中存储数据的示例,而不更改应用程序逻辑
使用
在使用docker volume create或驱动容器建立匿名卷时,能够指定一个volume drivers。下面的例子使用vieux/sshfs做为volume drivers
假设有2个节点,第一个节点是Docker主机,它能SSH到第二个节点
一、在Docker主机中,安装vieux/sshfs插件

二、使用卷驱动建立卷
1)建立命名卷

2)启动容器时使用卷驱动建立匿名卷

三、备份、恢复、迁移数据卷
1)备份一个容器

- 启动一个新容器,挂载dbstore容器中的卷
- 挂载一个本地主机目录到容器/backup
- 使用tar将dbdata卷中的数据打包成backup.tar
2)用备份恢复容器
使用刚刚建立的备份来恢复容器:

而后,在新建立的容器的卷中使用tar解包备份的数据:
喜欢就点个赞吧,主页有Java架构交流圈!