76.[Docker]容器的数据管理

来源:互联网 发布:mysql source 导入文件 编辑:程序博客网 时间:2024/06/05 16:00

  • 数据卷
    • 添加数据卷
    • 访问数据卷
    • 本机路径作为数据卷
    • 将共享卷挂载为数据卷
    • 卷标签
    • 挂载本机文件作为数据卷
  • 数据卷容器
  • 卷操作
    • 备份恢复迁移数据卷
    • 查看卷列表
    • 删除卷
  • 注意事项

转载请注明出处:http://blog.csdn.net/a464057216/article/details/73469094

容器内管理数据或容器间共享数据有两种方式:

  • 数据卷
  • 数据卷容器

数据卷

数据卷是一个有别于UnionFS(联合文件系统,Union File System)、可以供一个或多个容器使用的特定目录,用于数据持久化或数据共享。

  • 数据卷在容器创建时初始化。如果容器内的镜像在挂载点包含数据,这些数据在卷初始化时会被拷贝到新卷中(但是挂载点是主机路径时不适用,挂载宿主机目录时,宿主机目录中的内容会覆盖原挂载点中的数据)。
  • 数据卷可以在容器间共享和重用。
  • 对数据卷的改动直接生效。
  • 镜像更新不会包含数据卷的更新。
  • 容器被删除后,其使用的数据卷仍然存在,即数据卷的生命周期与容器的生命周期无关,也不会有自动垃圾回收机制。

添加数据卷

使用docker createdocker run命令的-v参数可以为容器添加数据卷,可以多次使用-v参数挂载多个数据卷,比如:

# Written by: CSDN - Mars Loo的博客$ docker run -d -P --name web -v /webapp training/webapp python app.py324aff2f4b74482a5988157ee28c2f088ea3d688f1eb1063c3ea5e0d56d6a22b

在容器内部添加/webapp的数据卷。在Dockerfile中使用VOLUME指令添加一个或多个数据卷。

访问数据卷

上面添加的/webapp卷是容器内的文件系统,通过docker inspect <container-name>可以查看其映射的宿主机文件系统位置:

# Written by: CSDN - Mars Loo的博客$ docker inspect web

这里写图片描述

Source表示宿主机位置,Destination表示容器内的位置,"RW": true表示数据卷是可读写的。

本机路径作为数据卷

# Written by: CSDN - Mars Loo的博客$ docker run -d -P --name web -v /home/mars/webapp:/webapp training/webapp python app.pyba6bf3e2f3d52e6fa13226dcf5837a3da09061ca304c6d52b84783a56a9ad114

将本机的/home/mars/webapp目录挂载到容器的/webapp卷,如果容器内的/webapp卷已经存在数据,旧数据不会被清除,而是直接覆盖为/home/mars/webapp中的内容,将/home/mars/webapp取消挂载后,原始数据就会恢复出来,这与mount命令的行为是一致的。

-v参数前面的主机路径可以是绝对路径或名字值,容器内路径必须是绝对路径。如果主机路径使用绝对路径并且该路径不存在,则Docker引擎会自动创建这个路径。如果主机路径使用名字,必须以字母或数字开头,后面跟字母、数字、下划线、短横线或点号,Docker引擎会创建一个命名卷挂载到容器内的目录上,比如:

# Written by: CSDN - Mars Loo的博客$ docker run -d -P --name web -v foo:/webapp training/webapp python app.py0b5552be46d5dc3d91fed8791202415dfaea7deeac63ee382c42f0e2ae0bb212

查看容器详细信息:
这里写图片描述

如果在Mac或Windows上使用Docker,默认只允许Docker挂载宿主机/Users(Mac)目录或C:\Users(Windows)目录,所以-v参数可以指定为-v /Users/<path>:/<container path>-v C:\Users\<path>:/<container path>

将主机路径挂载到容器中,可以很方便在宿主机目录中调试代码,在容器里实时查看效果。

默认挂载点为可读写属性,也可以将挂载点设置为只读:

# Written by: CSDN - Mars Loo的博客$ docker run -d -P --name web -v /home/lmz/webapp:/webapp:ro training/webapp python app.pybff56c7b2a2d1712df5ead7350c916133b84dad34abcbc53bf8954fdeb83c876

查看容器详细信息:
这里写图片描述

如果在Mac上使用Docker,可以开启cached选项提高读负载重的应用性能(以牺牲部分数据一致性为代价):

# Written by: CSDN - Mars Loo的博客$ docker run -d -P --name web -v /home/lmz/webapp:/webapp:cached training/webapp python app.py

在其他操作系统上,是否开启cached选项没有区别。

将共享卷挂载为数据卷

将本机路径挂载到数据卷是受限于主机的,不符合Docker到处可用到处一致的原则。通过数据卷插件可以挂载共享卷,比如iSCSI、NFS、FC等,这样只要运行容器的主机有访问网络文件系统的权限并且安装了插件,即可保持数据一致性。
通过docker run命令可以使用数据卷驱动,数据卷驱动通过名字创建数据卷,比如:

# Written by: CSDN - Mars Loo的博客$ docker run -d -P  --volume-driver=convoy -v my-named-volume:/webapp --name web training/webapp python app.py

convoy卷驱动是一个支持多种存储后端的插件(使用前需要正确安装和配置:https://github.com/rancher/convoy#quick-start-guide),运行该命令创建了一个名为my-named-volume的命名数据卷,并挂载到容器的/webapp目录。

或者先使用docker volume create命令创建一个数据卷,然后再在容器中使用。下面创建了名为my-named-volume的数据卷,配置选项通过0=<key>=<value>的格式指定:

# Written by: CSDN - Mars Loo的博客$ docker volume create -d convoy --opt o=size=20GB my-named-volume$ docker run -d -P -v my-named-volume:/webapp --name web training/webapp python app.py

所有可用的卷插件可以参考:https://docs.docker.com/engine/extend/legacy_plugins/。

卷标签

SELinux要求挂载到容器的数据卷中的内容有正确的标签。如果没有标签,安全系统会阻止容器内的进程使用挂载点的数据。默认情况下,Docker不会修改系统设置的标签。

如果要在容器内修改标签,可以在挂载时使用:z:Z参数修改共享卷的安全标签。:z告诉Docker为数据打上共享内容标签,允许所有容器读写数据。:Z告诉Docker为数据打上私有非共享标签,只有当前容器可以访问私有卷。

挂载本机文件作为数据卷

除了使用本机目录作为挂载点,也可也挂载文件:

# Written by: CSDN - Mars Loo的博客$ docker run --rm -it -v ~/.bash_history:/root/.bash_history ubuntu /bin/bash

这样容器内有本机的Bash历史,退出后,本机也记录了容器内的操作历史。
文件编辑软件或工具如vised --in-place会改变文件的inode,所以在Docker中编辑挂载点的文件会报错,建议此时挂载待编辑文件的整个父级目录。

数据卷容器

如果想在容器间共享持久化数据,创建命名的数据卷容器然后从其中挂载数据比较好。数据卷容器其实是一个正常的容器,专门用来提供数据卷供其它容器挂载的。比如:

$ docker create -v /dbdata --name dbstore training/postgres /bin/truebf09e711f291a642f047eeb25ae39c1fb3f29a417c75a25f9a148d2dd7368c05

因为数据卷容器不运行应用,所以使用已有的training/postgres的层(layers)会节省硬盘空间。在其他容器中可以通过--volumes-from选项间接挂载/dbdata卷:

# Written by: CSDN - Mars Loo的博客$ docker run -d --volumes-from dbstore --name db1 training/postgres1aecafeb97528638a5746b8a6d0241576091f010d7b165470cc8d577e1b7a327

启动第二个容器:

# Written by: CSDN - Mars Loo的博客$ docker run -d --volumes-from dbstore --name db2 training/postgresb2b04ca5149b4b6b2153a2f32552ff2c585c9284242bb36bdf4a2fce68377179

如果postgres镜像包含/dbdata目录,则会挂载dbstore容器的/dbdata目录而隐藏postgres镜像中/dbdata目录中的内容。

docker run命令中,可以多次使用--volume-from从多个不同的数据卷容器挂载。也可以扩展挂载链,通过挂载db1间接挂载dbstore中的卷:

# Written by: CSDN - Mars Loo的博客$ docker run -d --name db3 --volumes-from db1 training/postgres

删除容器时,容器中的卷不被删除,如果要删除卷,需要在最后一个对卷有引用的容器被删除时,使用-v选项,比如:docker rm -v db1,如果删除某个容器时使用了-v参数但是该卷实际上还在被其他容器使用,卷也不会被删除。

如果删除容器时未提供-v参数,可能会在系统中残留很多无用的卷,可以使用docker volume ls -f dangling=true查询,然后通过docker volume rm <volume name>删除无用的卷,或者直接用一条命令docker volume prune删除无用卷。

卷操作

备份、恢复、迁移数据卷

备份数据卷中的数据到宿主机当前目录中:

# Written by: CSDN - Mars Loo的博客$ docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata

恢复备份的数据,首先创建一个新的容器(也可以是已经存在的容器):

# Written by: CSDN - Mars Loo的博客$ docker run -v /dbdata --name dbstore2 ubuntu /bin/bash

然后解压缩已备份的数据:

# Written by: CSDN - Mars Loo的博客$ docker run --rm --volumes-frome dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata &&  tar xvf /backup/backup.tar --strip 1"

组合上面的方法可以实现自动化地数据备份、迁移、恢复等。

查看卷列表

# Written by: CSDN - Mars Loo的博客$ docker volume lsDRIVER              VOLUME NAMElocal               8c1aa1ad95b781251148e9529414304360aa7992dbc3495ead82126e91fd4121

删除卷

可以创建命名卷或匿名卷。如果创建容器的时候使用如下命令:

# Written by: CSDN - Mars Loo的博客$ docker run --rm -v /foo -v dbstore:/bar busybox top

挂载了两个卷,当容器被删除时,会自动删除匿名卷(挂载到/foo目录的),而不会自动删除名字为dbstore的命名卷。

注意事项

多个容器间可以共享一个或多个数据卷,但是多个容器同时向一个共享卷写数据时会造成数据损坏,需要从程序设计上解决并发写入问题。
数据卷通过一般的Linux操作也可以读写,但是一般情况下不建议这么做,可能会引起数据损坏。

如果觉得我的文章对您有帮助,欢迎关注我(CSDN:Mars Loo的博客)或者为这篇文章点赞,谢谢!

原创粉丝点击