Skip to content

数据与数据卷


我们知道,Docker容器拥有沙盒隔离,容器的相关操作和数据流动相对封闭,容器与容器相隔离,容器与外部也相隔离。数据的共享、传输等操作就相对麻烦。

Docker通过UFS,将宿主机的文件/目录挂载到容器中,并让容器内外共享,使得容器数据与宿主机能够直接联通。这样做的另一个好处就是不必担心数据的持久化,因为直接挂载到了宿主机上,也就是硬盘中。

文件挂载

Docker有三个不同的文件挂载方式

  1. Bind Mount(绑定挂载)
    • 绑定挂载允许将宿主机的文件或目录挂载到容器中,实现宿主机和容器之间的共享。
    • 这意味着容器中的更改会直接影响宿主机中的文件,反之亦然。
    • 这种挂载方式使得容器内的数据可以持久化保存在宿主机上。
  2. Volume(卷)
    • 卷是一种特殊的目录,它可以绕过容器文件系统并直接管理容器数据。
    • 卷可以提供持久化的存储,并且可以在容器之间共享和重用。
    • 使用卷可以更有效地管理数据,并使得容器的数据可以独立于容器的生命周期而存在。
  3. Tmpfs Mount(临时文件系统挂载)
    • Tmpfs 是一种基于内存的临时文件系统,它允许将临时文件系统挂载到容器中。
    • 与绑定挂载和卷不同,Tmpfs Mount 仅在容器运行时存在,并且数据存储在内存中。
    • 一旦容器停止运行,Tmpfs Mount 中的数据也会被清除。

简而言之,前两种是通过硬盘挂载,最后一种通过内存挂载;第一种挂载方式需要手动指定目录,第二种是通过Docker自动执行。

挂载命令

从使用和记忆角度,三种不同的挂载命令有如下区别

Bind Mount

  • -v 指定两个目录(host dir:container dir)

Volume

  • -v 指定一个目录(host dir)

Tmpfs Mount

  • --tmpfs 指定一个目录(host dir)

Bind Mount

挂载一般在容器创建的时候通过-v选项

docker run -d --name xxx -v <host dir>:<container dir> ooo

* 以只读方式存储,<host dir>:<container dir>:ro   (ro指的是readonly),对应的是容器中Mounts里的RW
  docker run -d --name xxx -v <宿主机目录>:<Container目录>:ro ooo
* 这里的目录必须需要通过绝对目录的形式

查看详细情况

docker inspect <container-name / containerID / alias>
* 在Mounts中可以看到挂载相关信息

Volume

通过volume方法挂载,不需要指定宿主机目录,所以参数传递只需要传递容器目录即可,这也是在使用方面Bind Mount和Volume的区别之一

如果数据卷存在会直接引用,如果不存在会创建一个数据卷

docker urn -d --name xxx -v <contrainer dir> ooo

除此之外,因为volume同container等隔离,volume可以单独创建

docker volume create <volume-name>

查看创建的数据卷

docker volume ls

删除数据卷,不过因为需要指定数据卷名称,而很多数据卷都是自动命名,所以实际上并不好用

docker rm <volume-name>

在容器删除时,联级删除相关的数据卷,以节约资源

docker rm -v <volume-name>

删除没有被引用的数据卷,相当于手动GC

docker volume prune

Tmpfs Mount

与上述两种挂载方式不同的是,临时目录挂载需要通过--tmpfs指令指定

docker run -d --name xxx --tmpfs <host dir> ooo

查看容器情况

docker inspect <container-name>
* 在Tmpfs中可以看到关于tmpfs mount挂载相关信息

上文我们简单提及,Tmpfs Mount是通过内存进行储存的,虽然内存并没有持久储存的能力,但内存相较于硬盘而言其读写速度更快。适用于数据吞吐量较大且并不需要持久化储存的场景。

数据卷容器

多个数据卷可以通过数据卷容器进一步封装,隐藏配置细节,使其内聚更强,迁移更为便利。

数据卷容器持有内部数据卷的引用,不依赖于容器的运行。

docker create --name xxx -v <host dir> ooo

在创建容器时使用--volumes-from指定数据卷容器

docker run -d --name xxx --volumes-from <volume-container-name> ooo

数据备份与迁移

备份与迁移,本质上是打包-移动-解压的过程。通过创建临时容器,并结合数据卷容器可以很便捷地进行数据备份与迁移。

以下语句的意思是:通过Docker创建Bind Mount文件挂载并对数据卷容器引用的数据卷内的数据进行打包再把tar包迁移到宿主机目录中,完成操作后容器自动删除

docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar cvf /backup/backup.tar /webapp/storage

我们简单拆分一下这条语句

--rm 					结果是创建了临时容器。--rm的效果是停止后自动删除 
--volumes-from appdata	引用的数据卷容器
-v /backup:/backup		宿主机的backup:Docker中的backup
ubuntu					这里就是镜像名,没有使用--name重命名
tar cvf...				这里需要了解一个机制:镜像定义后接上命令,会替换掉镜像原本的主程序启动命令。 这里的效果就是通过Docker打tar包并存放到宿主机中

另外,可以通过--mount实现操作的颗粒化程度更高的挂载,如果习惯configure-like的操作,可以通过结合Linux的输出重定向、管道符等实现更为定制化的挂载,这里不再展开。