上一篇文章讲了 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 群与我探讨。
微信扫描二维码关注我们
如果觉得文章有帮助到你,可以点击下方的打赏按钮赞助下服务器费用。
文章评论
是不是应该对应写一份docker for windows给初学者呢,毕竟GUI结合少量script/cmdlet的方式更加便捷
@A.Z Docker For Windows 从根本上来说也是 Linux,只不过他是用虚拟机运行的 Linux,那个GUI没多大用处,还是用命令操作的。相对于 Linux 只有部分命令有区别,比如网络驱动。