Docker 新手入门:容器数据持久化

2019-06-25 3958点热度 2条评论

上一篇文章讲了 Docker 容器的使用方法,我们还在上一篇文章提到过,容器里的数据默认是会随容器的消失而消失的。

如果想让数据持久保留,需要用到 Docker 的绑定挂载功能,这个功能可以将宿主系统的文件或文件夹挂载到容器里,也可以使用 Docker 卷来创建一个卷并挂载到容器里。

下面我们就一起来了解下这两种方法以及如何使用。

Docker 数据持久化

导出及导入容器内的文件

讲数据持久化之前,先来说一下如何导出和导入容器里的文件。

如果想复制文件到容器里,或者是把容器里的文件复制出来,很简单,使用命令sudo docker cp

例如(假设容器正在后台运行):

在宿主系统创建一个文件夹:sudo mkdir /tmp/test

在宿主系统创建一个文件并写入 Hello World:sudo echo "Hello World" > /tmp/test/test.txt

然后把这个文件复制到容器里:sudo docker cp /tmp/test/test.txt mivm:/root/test.txt第一个参数是宿主系统的文件路径,第二个参数是容器名称加冒号加容器的目标路径,如果要把容器里的文件复制出来,两个参数反过来就可以了,例如:sudo docker cp mivm:/root/test.txt /tmp/test/test.txt

使用容器读取刚刚复制进去的文件:sudo docker exec mivm cat /root/test.txt,没有意外的话,会输出 Hello World。

Docker 绑定挂载

Docker 绑定挂载可以让宿主系统的文件夹挂载到容器里,常用于文件共享,也可以用于数据持久化,不过官方更推荐使用 Docker 卷(等会讲)。

绑定挂载需要在创建容器的时候进行挂载,挂载的方式也很简单,只需要添加-v参数。

例如:

在宿主系统创建一个文件夹:sudo mkdir /tmp/test

在宿主系统创建一个文件并写入 Hello World:sudo echo "Hello World" > /tmp/test/test.txt

创建一个容器将刚刚创建的文件夹挂载到容器里:sudo docker run -itd -v /tmp/test:/test --name mivm alpine /bin/sh-v后面的两个参数,第一个是宿主系统路径,第二个是挂载目标路径,不知可以用来挂载文件夹,单纯的用来挂载文件也是可以的,而且可以挂载多个,只需要添加多个-v即可,如果宿主系统里不存在文件夹,Docker 会自动创建文件夹。

使用容器读取刚刚挂载的文件夹的文件:sudo docker exec mivm cat /test/test.txt

使用容器向挂载点写入文件:sudo docker exec mivm /bin/sh -c "echo \"Hello mivm\" > /test/mivm.txt"

在宿主系统里运行:sudo cat /tmp/test/mivm.txt

你会看到 Hello mivm,因为这个目录已经挂载到容器里了,不管是宿主系统还是容器,对文件夹的所有操作都会同步。

这是第一种数据持久化的方法,在大多数情况下都适用。

Docker 卷

上面的绑定挂载虽然在大多数情况下都使用,但是在某些情况下是不使用的。

举个栗子,我想让容器里的/usr/bin这个目录实现数据持久化,我能不能使用绑定挂载的方法,把宿主系统的目录挂载到容器里的/usr/bin呢?

我们来试一试,sudo docker run -itd -v /tmp/usr-bin:/usr/bin --name mivm alpine /bin/sh,然后列出容器里/usr/bin下的文件sudo docker exec mivm ls /usr/bin,奇怪,怎么什么都没有!

原因很简单,因为我们使用绑定挂载,会使容器里的原文件被覆盖,导致容器里的目录被我们的空目录覆盖了,所以就什么都没了。

如果想持久化容器里已有的文件,需要创建一个 Docker 卷,把卷挂载到容器里的/usr/bin,由于 Docker 卷的特性,新卷可以通过容器预先填充内容,所以容器里的/usr/bin的内容会被写入到卷里。

例子:

创建一个卷:sudo docker volume create mivm-data,此命令会创建一个名为 mivm-data 的卷,如果要查看已创建的卷,使用命令sudo docker volume ls,如果要删除已创建的卷,使用命令sudo docker volume rm <name>,删除卷之前先确保卷没有被容器使用。

创建一个容器将刚刚创建的卷挂载到容器里:sudo docker run -itd -v mivm-data:/usr/bin --name mivm alpine /bin/sh-v后面的两个参数,第一个是卷名称,第二个是挂载目标路径,卷名称必须存在,Docker 不会自动创建卷。

再来列出容器里的文件试一试:sudo docker exec mivm ls /usr/bin

文件又有了,我们来测试一下数据能不能持久化。

使用容器向挂载点写入文件:sudo docker exec mivm /bin/sh -c "echo \"Hello mivm\" > /usr/bin/mivm.txt"

结束并删除掉容器:sudo docker stop mivm && sudo docker rm mivm

重新创建容器并挂在卷:sudo docker run -itd -v mivm-data:/usr/bin --name mivm alpine /bin/sh

读取我们刚刚写入的文件:sudo docker exec mivm cat /usr/bin/mivm.txt

你会看到 Hello mivm,证明我们的数据持久化了。

如果你想在删除容器的同时删除挂载卷,可以添加-v参数,例如:sudo docker rm -v mivm


好了,以上就是如何让 Docker 容器数据持久化的两种方法,大家根据自己的需求选择对应的方法,更多信息可以参考:https://docs.docker.com/storage/

有任何不懂的问题,欢迎加入 QQ 群与我探讨。

微信公众号二维码

微信扫描二维码关注我们

如果觉得文章有帮助到你,可以点击下方的打赏按钮赞助下服务器费用。

小山

一个什么都不会但要装作很厉害的人

文章评论

  • A.Z

    是不是应该对应写一份docker for windows给初学者呢,毕竟GUI结合少量script/cmdlet的方式更加便捷

    2019-07-13
    • 小山

      @A.Z Docker For Windows 从根本上来说也是 Linux,只不过他是用虚拟机运行的 Linux,那个GUI没多大用处,还是用命令操作的。相对于 Linux 只有部分命令有区别,比如网络驱动。

      2019-07-13
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    回复 A.Z 取消回复

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据