智慧屏安装APP的最佳实践与跨平台小程序开发的结合
1155
2022-11-18
docker学习笔记(4)- 应用数据管理(容器外)
简介
docker storage driver支持了image分层存储和容器可写层的存储管理,使用挂载主机目录的方式可以将数据存储在主机的文件系统上或内存中。
之前学习过镜像的分层存储,以Dockerfile构建镜像每行有关数据写入的命令会给镜像增加一层,容器基于镜像启动,会在镜像最上层之上再启动一层可写层(writable layer),如果容器被删除,那么该可写层也会消失,所以容器内的可写层不宜用来对需要持久化的数据做存储,应当存储一些临时数据,这些数据不影响应用的后续使用,比如之前使用的busybox用来执行wget、ping等命令,执行期间产生的数据我们无需保存,即使容器被删除,后面再次使用时启动新容器还是可以达到相同的目的。可以使用volumes和bind mounts的方式将数据存储在主机上,这样即使容器被删除,数据仍然在,而且很容的对数据进行迁移与共享。由于容器可写层需要storage dirver的支持,需要通过内核提供一个union filesystem,维护了额外的数据结构,相较于直接使用数据卷性能更差些,具体的实现方式在后面研究相关底层技术再记录,先整理下存储卷的相关知识。
挂载方式
有三种挂载方式将容器内部数据存储到主机上,Volumes、bind mounts、tmpfs mounts
Volumes
由docker创建和管理,主机上的其他程序不可修改,将数据卷存储在主机的一片区域上(linux路径/var/lib/docker/volumes/),使用某个volume其实是将该volume在主机上的目录mount到容器内,如果该目录下已有内容,则原有的数据会被复制到volume中。
使用场景
多个容器共享数据,多个容器可以同时挂载一个volume允许使用volume driver,不需要更改应用程序,通过更换volume dirvier存储容器数据到远端主机或云端(例如NFS or S3)备份和迁移数据
# 创建volumedocker volume create volume-test1# 查看volume详细信息docker volume inspect volume-test1# 删除volume,只有没有任何容器使用时才可删除(包括停止的容器)docker volume rm volume-test1
启动容器时指定volume参数
# 启动容器nginx1,卷volume-test1挂载到nginx1内部的/app路径下docker run -d \ --name nginx1 \ --mount source=volume-test1,target=/app \ nginx:latest
如果将新建的volume挂载到容器某个目录下,并且该目录下已有内容,那么会将这些内容拷贝到volume中,其他容器使用该volume时也可以看到
使用volume driver
例如,使用vieux/sshfs驱动允许容器使用sshfs挂载远端文件夹
# -vieux/sshfs驱动插件docker plugin install --grant-all-permissions vieux/sshfs# 使用vieux/sshfs驱动创建volume,驱动配置选项通过-o指定docker volume create --driver vieux/sshfs \ -o sshcmd=test@node2:/home/test \ -o password=testpassword \ sshvolume1# 启动时创建并使用volume,volume-opt指定使用volume需要的参数docker run -d \ --name sshfs-container \ --volume-driver vieux/sshfs \ --mount src=sshvolume2,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \ nginx:latest
创建CIFS/Samba volume,可以直接使用容器挂载samba文件夹
# local是默认的driverdocker volume create \ --driver local \ --opt type=cifs \ --opt device=//uxxxxx.your-server.de/backup \ --opt o=addr=uxxxxx.your-server.de,username=uxxxxxxx,password=*****,file_mode=0777,dir_mode=0777 \ --name cif-volume
备份volume
# 创建一个容器dbstoredocker run -v /app --name dbstore ubuntu /bin/bash# 再创建一个新容器,将主机当前目录$(pwd)挂载到新容器/backup目录下,新容器与容器dbstore共享其volume,之后运行新容器执行tar cvf /backup/backup.tar /app将/app目录归档到/backup/backup.tar下面(即主机$(pwd)下面)docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /app
恢复
# 创建新的容器 docker run -v /dbdata --name dbstore2 ubuntu /bin/bash# 共享新容器的volume卷,并将备份文件所在目录$(pwd)挂载到当前容器/backup下,解压backup.tar到容器dbstore2的/dbdatadocker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar"
bind mounts
与volume不同的是,除了可以挂载目录,还可以挂载文件到容器内。可以提供更好的性能,具体效果依赖主机使用的文件系统。因为使用绝对路径与主机目录绑定,所以容器的移植性较volume更弱,隔离性差(其他程序也可以修改该路径的内容)。可以对容器设置只读或读写权限
使用场景
将源代码目录挂载到容器中,在主机修改代码,可以看到容器应用的变化效果共享主机文件到容器,比如将主机的/etc/resolv.conf挂载到容器,为容器提供DNS解析
使用bind mounts
# 使用bind mounts,将主机target目录挂载到容器/app下,容器对该目录有只读权限docker run -d \ -it \ --name devtest \ --mount type=bind,source="$(pwd)"/target,target=/app,readonly \ nginx:latest
如果容器目录已有内容,将主机目录bind mounts到该目录下时,容器该目录下原有的内容被隐藏,只显示主机目录下已有的内容
tmpfs mounts
tmpfs mounts方式与上两种不同,是将容器内该挂载点下的内容写到主机内存中,容器停止时候,挂载点被移除,这些内容就会丢失。
使用场景
存放一些临时的敏感信息(不想将其存放到主机或容器中)容器应用需要写入大量的非持久化数据时提高性能
使用tmpfs mounts
# 运行容器,使用tmpfs mounts到容器的/app目录下,设置容器内使用权限为770,/app目录大小为10Mdocker run -d -it \ --name tmptest \ --mount type=tmpfs,destination=/app,tmpfs-mode=1770 tmpfs-size=10m\ nginx:latest
默认tmpfs mounts不对目录大小做限制
小结
对于以上三种挂载方式,bind mounts与volumes的使用与功能差异较小,通过表格的方式对比下:
对比项(source:主机;dest:容器) | bind mount | volume |
---|---|---|
创建时主机路径不在 | 报错 | 自动创建 |
source路径 | 使用时指定 | /var/lib/docker/volumes |
source路径为空 | 隐藏dest,显示source内容 | 将dest内容复制到source后显示source内容 |
source路径不为空 | 隐藏dest,显示source内容 | 隐藏dest,显示source内容 |
可移植性 | 弱(绑定主机路径) | 强(docker完全控制,不依赖主机路径) |
主机程序访问 | 容易(chown修改用户组即可访问) | 受限(需root用户) |
学习自:
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~