使用 Volume 保存容器内的数据

2 阅读3分钟

之前说过 每个 container 都是独立 的,想象一下,你有一个正在运行的 mysql:5.5 容器,现在想升级到 mysql:5.7,如果直接停掉旧版本容器再启动新版本,数据库里的数据可就全部丢失了。这时 Volume 就派上用场了,它的作用就是持久化存储容器内的数据。

图片

当你使用 volume 时,docker 会在你的本机上随机创建一个文件夹,默认通常位于 /var 底下,然后让这个文件夹跟 container 里面的某个文件夹进行绑定映射。

因为他们是互通的,所以当你 container 里面的文件夹里有任何变更时,本地的文件夹也会跟着变,而且很重要的一点是: container 被删掉时宿主机上的文件夹并不会删除 ,因此 我们可以利用这个特性保留容器里面的数据

命名数据卷

是由Docker创建和管理的独立于容器生命周期的数据存储区,通过一个自定义名称进行引用,而不是直接与宿主机上的某个特定路径关联。

创建 volume

我们创建了一个 volume 叫做 db-data,完成之后可以看到多了一个 volume,这时候 docker 已经在本机上创建一个文件夹给这个 volume 用了。

> docker volume create --name db-data
> docker volume ls

图片

使用 volume

在启动时加一个 -v 参数,就可以指定 volume 要跟容器内哪一个文件夹映射,我使用的是 /db/data ,实际上使用时可以换成数据库存放数据的路径。

  1. 刚开始先确认 /db/data 里面什么文件都没有

  2. 接着在容器内创建一个文件 file

  3. 最后再查看文件是否存在

> docker run -v db-data:/db/data -it ubuntu ls -la /db/data
> docker run -v db-data:/db/data -it ubuntu touch /db/data/file
> docker run -v db-data:/db/data -it ubuntu ls -la /db/data

图片

这三个指令是跑在不同的容器里面 ,所以也就证明了 当容器被关掉时,数据确实还有保存在 volume 内 ,而且下个容器可以成功读到上个容器留下的数据

删除 volume

当 volume 不再需要了,可以将它们刪除。指令为 docker volume rm {volume名称}。指令如下:

docker volume rm db-data

要注意的是,当沒有任何容器在使用此 volume 时,才可以刪除。

宿主机目录挂载

上面那种先 create 再使用的 volume 称作命名数据卷 ,而现在要介绍另外一种叫做宿主机目录挂载 ,是将宿主机上的某个目录作为数据源,将其内容映射到Docker容器内部的一个目录,这样容器内部的文件操作会反映到宿主机对应的目录上。

  1. 检查 ~/app 内没有 package.json

  2. 指定本机的 ~/app 跟容器内的 /app 映射,接着在容器内运行 npm init

  3. 运行完后再回本机确认有没有创建出 package.json

> ls -la app
> docker run -v ~/app:/app --workdir /app node:slim npm init -y
> ls -la app

图片

上面例子中的 package.json 其实是在容器内生成的,所以有了 volume 之后就可以不用装 yarn 却还是可以跑 yarn init

同理,你也可以不用装 g++ 就能编译 C++ 源代码、不用装 JDK 就可以开发 Java 程序、甚至不用装 MongoDB 就可以用他来存数据,整个电脑只要装一个 docker 就可以开发任何语言的程序。

总结

本文介绍了两种类型的 Volume:命名数据卷和宿主机目录挂载,都是用来实现容器内外数据持久化的。有了 Volume,无论是升级软件版本还是重新部署容器,都能确保重要数据的安全性与完整性。