Docker容器的数据卷
数据卷是Docker容器的重要技术之一
什么是数据卷?
docker的理念之一就是将应用和运行的环境打包,因此docker容器的生存周期通常都是与在容器中运行的程序相同的,而我们对数据的要求是持久化,docker容器之间也需要一个共享数据的渠道。这些需求就催生了docker数据卷的诞生。
docker数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问
数据卷设计的目的,在于数据的永久化,它完全独立于容器的生命周期。因此,docker不会在容器删除时删除其挂在的数据卷,也不会存在类似的垃圾收集机制,对容器引用的数据进行处理
docker数据卷的一些特性:
docker数据卷独立于docker存在,与docker容器的生存周期分离
存在于宿主机(docker host)中
docker数据卷,可以是目录,也可以是文件
docker容器可以利用数据卷技术与宿主机进行数据共享
同一个目录/文件可以支持多个容器的访问,这样实现了容器之间的数据共享访问
Docker数据卷的特点:
数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中
数据卷可以在容器之间共享和重用
可以对数据卷里的内容直接进行修改
数据卷的变化不会影响镜像的更新
即使挂载数据卷的容器已经被删除,卷也会一直存在
数据卷的使用
为容器添加数据卷使用-v选项:
docker run -v ~/container_data:/data -it IMAGE /bin/bash
[root@localhost system]# docker run -it -v ~/datavolume:/data test1 /bin/bash root@998c59ce40ea:/# ls bin boot data dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@998c59ce40ea:/# cd /data root@998c59ce40ea:/data# echo "I am in container" > /data/fsx
上面是在docker容器中的操作,给/data目录下存放数据,查看宿主机的~/datavolume
[root@localhost ~]# cd datavolume/ [root@localhost datavolume]# ls fsx [root@localhost datavolume]# cat fsx I am in container
为数据卷添加访问权限
添加数据卷访问权限
docker run -v ~/datavolume:/data:ro -it ubuntu /bin/bash
[root@localhost datavolume]# docker run -it -v ~/datavolume:/data:ro --name volume_1 test1 /bin/bash root@48813214b14e:/data# touch fsx_2 touch: cannot touch 'fsx_2': Read-only file system root@48813214b14e:/data# cat fsx I am in container
使用Dockerfile创建包含数据卷的镜像
Dockerfile指令:
VOLUME [ "/data"]
在Dockerfile中创建的数据卷不能映射到已经存在的本地文件目录中,在镜像构建时指定的数据卷会在容器启动时创建指定名字的数据卷,并且运行同样镜像的不同容器创建的数据卷是不同的。
[root@localhost docker]# cat Dockerfile FROM ubuntu:latest VOLUME ["/data/volume1","/data/volume2"] CMD /bin/bash [root@localhost docker]# docker build -t="volume_test" . Sending build context to Docker daemon 2.048 kB Step 1/3 : FROM ubuntu:latest ---> 07c86167cdc4 Step 2/3 : VOLUME /data/volume1 /data/volume2 ---> Running in cb0a6ace7e4c ---> 9e8f2795cf59 Removing intermediate container cb0a6ace7e4c Step 3/3 : CMD /bin/bash ---> Running in e92ceb4d14e0 ---> e489cd7388ff Removing intermediate container e92ceb4d14e0 Successfully built e489cd7388ff [root@localhost docker]# docker run -it --name volume1 volume_test root@3ae2728f44ab:/# cd data/ root@3ae2728f44ab:/data# ls volume1 volume2 root@3ae2728f44ab:/data# cd volume1/ root@3ae2728f44ab:/data/volume1# ls root@3ae2728f44ab:/data/volume1# touch fsx_test root@3ae2728f44ab:/data/volume1# echo "a new volume test" >> fsx_test [root@localhost volumes]# tree . . ├── 1e0e89033f57892c086dbe29b84efd20da2e6c2a1e70d51acb7575253a394e58 │ └── _data ├── 25533687846bb92be45ecf426a1ca665015b5bfaf6a5d310f49a6710d860f578 │ └── _data │ └── fsx_test //这就是创建的文件 [root@localhost volumes]# pwd /var/lib/docker/volumes //宿主机对应的挂载点
Docker的数据卷容器
Docker的容器也可以通过挂载包含数据卷的容器来实现数据卷共享。所以,一个数据卷容器:命名的容器挂载数据卷,其他容器通过挂载这个容器实现数据共享,挂载数据卷的容器,就叫做数据卷容器
构建一个数据卷容器
上一节构建了一个数据卷镜像,即: [root@localhost docker]# cat Dockerfile FROM ubuntu:latest VOLUME ["/data/volume1","/data/volume2"] CMD /bin/bash [root@localhost docker]# docker build -t="volume_test" . 根据该镜像创建一个数据卷容器 [root@localhost docker]# docker run -it --name dvt1 volume_test root@0b0335c61346:/# cd data/ root@0b0335c61346:/data# ls volume1 volume2 root@0b0335c61346:/data# cd volume1/ root@0b0335c61346:/data/volume1# ls root@0b0335c61346:/data/volume1# touch fsx_test root@0b0335c61346:/data/volume1# echo "a new volume test" >> fsx_test root@0b0335c61346:/data/volume1# exit
挂载数据卷容器的方法:
docker run --volumes-from CONTAINER_NAME ...
创建一个新的容器,并挂载刚才创建的数据卷容器dvt1
[root@localhost docker]# docker run -it --name dvt2 --volumes-from dvt1 ubuntu /bin/bash root@e0ba23efa99f:/# ls bin boot data dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@e0ba23efa99f:/# cd data/volume volume1/ volume2/ root@e0ba23efa99f:/# cd data/volume1/ root@e0ba23efa99f:/data/volume1# ls fsx_test root@e0ba23efa99f:/data/volume1# cat fsx_test a new volume test
使用inspect命令查看挂载细节:
[root@localhost docker]# docker inspect dvt2 | grep volume "Source": "/var/lib/docker/volumes/42daabbfe04de5109d3ea8533a2a436e9f270bf5f95acc2cb14caa27fdd4ac60/_data", "Destination": "/data/volume1", "Source": "/var/lib/docker/volumes/54f4f0457438f2577f7854178c7fbd109843c6800cb10b367c03983fb1679953/_data", "Destination": "/data/volume2", [root@localhost docker]# docker inspect dvt1 | grep volume "Type": "volume", "Source": "/var/lib/docker/volumes/42daabbfe04de5109d3ea8533a2a436e9f270bf5f95acc2cb14caa27fdd4ac60/_data", "Destination": "/data/volume1", "Type": "volume", "Source": "/var/lib/docker/volumes/54f4f0457438f2577f7854178c7fbd109843c6800cb10b367c03983fb1679953/_data", "Destination": "/data/volume2", "Image": "volume_test", "/data/volume1": {}, "/data/volume2": {}
Dcockerfile的数据卷容器的意义:
实现容器之间的数据共享
不需要让使用者得到确切的docker宿主机的目录,不暴露服务器的实际目录
如果删除了数据卷容器,挂载到数据卷容器其他的容器会怎么办?
[root@localhost volumes]# docker rm dvt1 dvt1 [root@localhost volumes]# docker start dvt2 dvt2 [root@localhost volumes]# docker attach dvt2 root@e0ba23efa99f:/# ls bin boot data dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var root@e0ba23efa99f:/# cd data/volume1/ root@e0ba23efa99f:/data/volume1# ls fsx_test root@e0ba23efa99f:/data/volume1# cat fsx_test a new volume test root@e0ba23efa99f:/data/volume1# pwd /data/volume1
所以:即使删除了数据卷容器,也不影响其他容器对数据卷的使用。数据卷容器只是做了一个数据卷信息的传递。
如果在删除数据卷容器时,加入-v选项,就是同时删除挂载的宿主机数据卷。但是,如果该数据卷还在被其他的容器使用,就不能删除。
Docker数据卷的备份和还原操作
docker数据卷的目的就是保存数据,备份和还原是必须可以实现的。
Docker数据卷数据备份
数据备份方法:
docker run --volumes-from [CONTAINER_NAME] -v $(pwd):/backup ubuntu
挂载需要备份的容器,并且指向挂载目录,-v指定保存数据的目录
tar cvf /back/backup.tar [container data volume]
容器运行时,执行tar命令
具体示例:
创建启动dvt4容器,并且添加选项,指定备份dvt1数据到宿主机的~/backup中,在运行容器时执行tar命令
[root@localhost volumes]# docker run --volumes-from dvt1 -v ~/backup:/backup --name dvt4 ubuntu tar cvf /backup/dvt1.tar /data/volume1 tar: Removing leading `/' from member names /data/volume1/ /data/volume1/fsx
在宿主机上可以查看到备份的数据
[root@localhost ~]# cd backup/ [root@localhost backup]# ls dvt1.tar [root@localhost backup]# tar xf dvt1.tar [root@localhost backup]# ls data dvt1.tar [root@localhost backup]# cd data/ [root@localhost data]# ls volume1 [root@localhost data]# cd volume1/ [root@localhost volume1]# ls fsx3
Docker数据卷数据还原
数据还原的方法:(就是数据解压所命令)
docker run --volumes-from [CONTAIN_NAME] -v $(pwd):/backup ubuntu
tar xcf /backup/backup.tar [container data vplume]
具体示例:
删除dvt1容器中/data/volume1/中的数据
[root@localhost volumes]# docker start dvt1 dvt1 [root@localhost volumes]# docker attach dvt1 root@d153e3ce4b4b:/# rm -rf data/volume1/*
还原dvt1容器中/data/volume1中的数据
[root@localhost volumes]# docker run --volumes-from dvt1 --name dvt5 -v ~/backup:/backup ubuntu tar xvf /backup/dvt1.tar data/volume1/ data/volume1/fsx3 [root@localhost volumes]# docker start dvt1 dvt1 [root@localhost volumes]# docker attach dvt1 root@d153e3ce4b4b:/# root@d153e3ce4b4b:/# ls /data/volume1/* fsx3