容器技术之Docker数据卷
前一篇随笔中我们了解了docker的网络相关说明,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/12952616.html;今天我们来聊一聊docker的数据管理相关说明;
在前面的博客中我们有强调过docker的镜像是分层构建的,把镜像启动为容器后,docker会加载只读层镜像并在镜像最顶层添加一个读写层;我们还说过该读写层不属于镜像属于容器;如果该容器宕掉了,那么随之镜像最顶层的读写层也随之消失;那么问题来了,如果之前运行的容器,在宕掉前在可写层生成的数据怎么保存下来呢?为了解决这个问题,我们先来看看docker的COW机制吧;
如上图所示,docker镜像是分层构建的,在最下面一层的数据到第二层或更高层有相同数据时,在上面一层的数据就会覆盖下面一层相同的数据;从而使得在上面一层和下面一层相同的数据只会存在一份,不同的数据都会存在;同样的道理,docker镜像通过层层镜像构建,在docker镜像最顶层看到的数据就应该是下面若干层重叠以后,相同的数据在最上层只会看到一份,而其他数据则是由下面若干层不同数据的叠加构成;在运行层容器时,容器内部看到的数据就是所有层镜像不同数据的集合和相同数据留一份的结果;如果运行过程中容器修改了现有文件,那么该文件就从读写层下面去复制一份到读写层,该文件的原来在只读层的文件还是存在,只是已经被读写层把该文件的副本隐藏了,这就叫docker的写时复制(cow)机制;
从上面的信息我们了解到docker容器在产生数据是在可写层,在修改数据时,会把原来的数据从原来只读层复制到可写层,从而隐藏原来的只读层的,但是只读层的数据还在;所以容器删除后,我们修改的数据不会保存到镜像,而是随容器的删除而删除;关闭并重启容器对于数据不受什么影响;我们现在有没有一种办法让读写层的数据保存起来,即便容器被删除后数据还依然可存在呢?
先来说说nfs数据共享吧;nfs共享是通过把一个目录通过网络的形式挂载到另外一个目录;从而实现往一个目录写数据时,就相当于把数据写到远端的目录的文件中;在docker容器中我们把这种类似的方式叫做卷;所谓卷就是容器上的一个或多个目录,此类目录可绕过联合文件系统,与宿主机上的某目录产生关联关系(绑定,类似nfs里的挂载);volume于容器初始化之时就会创建,由base image提供的卷中的数据会在此期间完成复制;volume的初衷是独立于容器的生命周期实现数据持久化,因此删除容器时,既不会删除卷,也不会对那些没有被引用的卷作垃圾回收操作;
卷为docker提供了独立于容器的数据管理机制;我们可以把镜像想象成静态文件,例如程序,把卷类比成动态内容,比如数据,于是镜像可以复用,而卷可以共享;卷实现了程序(镜像)和数据(卷)的分离;实现了容器之间的数据共享和复用,使得容器间传递数据变得高效方便;对数据卷内数据的修改会立马生效,无论是在容器中修改还是在本地操作;docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同而已;bind mount volume这种卷是由用户指定目录把存储上的一个目录挂载到容器内部的某个目录;docekr-managed volume这种卷是docker自己管理的卷,通常表现形式上把宿主机上的/var/lib/docker/vfs/dir/某个卷的ID 挂载到容器内部某个目录下;
示例:在的docker容器中使用docker-managed 类型的volume
[root@node1 ~]# docker run --name m2 -it --rm -v /mydata linux1874/myimg:v0.1 /bin/sh
/ # ls /
bin dev etc home mydata proc root sys tmp usr var
/ # cd /mydata/
/mydata # ls
/mydata # [root@node1 ~]# docker container inspect m2 -f {{.Mounts}}
[{volume 65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422 /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data /mydata local true }]
[root@node1 ~]# ll /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data
total 0
[root@node1 ~]# echo "hello world" > /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
[root@node1 ~]# cat /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
hello world
[root@node1 ~]# docker attach m2
/mydata # ls
aa.txt
/mydata # cat aa.txt
hello world
/mydata #
提示:-v只指定了一个目录表示指定容器内部的目录,它会通过docker daemon 自动在宿主机上生成挂载目录;像这种方式的挂载就叫做docker -managed类型的数据卷;从上面的信息可以看到我们可以用docker container inspect -f {{.Mounts}} 容器名称,来查看容器的卷、标识符以及挂载点主机目录信息;我们在生成的挂载目录下创建一个aa.txt的文件,然后在容器里/mydata里能够看到该文件和文件内容;
测试:我们把容器停掉看看数据卷是否会被删除呢?
[root@node1 ~]# cat /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
hello world
[root@node1 ~]# docker attach m2
/mydata # ls
aa.txt
/mydata # cat aa.txt
hello world
/mydata # exit
[root@node1 ~]#
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33c6f135eb86 linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 20 minutes ago Up 20 minutes m1
[root@node1 ~]# cat /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt
cat: /var/lib/docker/volumes/65db95bc3010530381e2bcc20fdd216329a502527e17a1e70c1cb7f6e2d2a422/_data/aa.txt: No such file or directory
[root@node1 ~]#
提示:在运行容器时如果使用了--rm选项,但容器停掉以后,对应挂载点数据卷会随之删除;
测试:运行容器不使用--rm选项,看看容器停掉后,是否还会删除数据卷?
[root@node1 ~]# docker run --name m2 -v /mydata -it linux1874/myimg:v0.1 /bin/sh
/ # ls /
bin dev etc home mydata proc root sys tmp usr var
/ # cd mydata/
/mydata # ls
/mydata # [root@node1 ~]# docker container inspect -f {{.Mounts}} m2
[{volume 28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e /var/lib/docker/volumes/28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e/_data /mydata local true }]
[root@node1 ~]# cd /var/lib/docker/volumes/28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e/_data
[root@node1 _data]# ls
[root@node1 _data]# echo "hello tom" > aa.txt
[root@node1 _data]# cat aa.txt
hello tom
[root@node1 _data]# docker attach m2
/mydata # ls
aa.txt
/mydata # cat aa.txt
hello tom
/mydata # exit
[root@node1 _data]#docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e6560584d41e linux1874/myimg:v0.1 "/bin/sh" About a minute ago Exited (0) 9 seconds ago m2
33c6f135eb86 linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 32 minutes ago Up 32 minutes m1
[root@node1 _data]# docker container rm m2
m2
[root@node1 _data]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33c6f135eb86 linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 35 minutes ago Up 35 minutes m1
[root@node1 _data]# cd
[root@node1 ~]# cd -
/var/lib/docker/volumes/28c477840d926c2fc33ebfacd607b84cfd5a272d279e1f966a65b7cb2f1d9a2e/_data
[root@node1 _data]# ls
aa.txt
[root@node1 _data]# cat aa.txt
hello tom
[root@node1 _data]#
提示:在不使用--rm选项运行容器,容器停止后删除容器,对于数据卷是不会被删除的;
示例:在docker容器中使用bind-mount 类型volume
[root@node1 ~]# mkdir /hostdir/v1 -p
[root@node1 ~]# docker run --name m3 -it -v /hostdir/v1/:/mydata linux1874/myimg:v0.1 /bin/sh
/ # ls /
bin dev etc home mydata proc root sys tmp usr var
/ # cd /mydata/
/mydata # ls
/mydata # [root@node1 ~]# docker container inspect -f {{.Mounts}} m3
[{bind /hostdir/v1 /mydata true rprivate}]
[root@node1 ~]# cd /hostdir/v1/
[root@node1 v1]# ls
[root@node1 v1]# echo "hello jerry" > aa.sh
[root@node1 v1]# cat aa.sh
hello jerry
[root@node1 v1]# docker attach m3
/mydata # ls
aa.sh
/mydata # cat aa.sh
hello jerry
/mydata # exit
[root@node1 v1]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
62ddbdc11a62 linux1874/myimg:v0.1 "/bin/sh" About a minute ago Exited (0) 4 seconds ago m3
33c6f135eb86 linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 41 minutes ago Up 41 minutes m1
[root@node1 v1]# docker container rm m3
m3
[root@node1 v1]# cd
[root@node1 ~]# cd -
/hostdir/v1
[root@node1 v1]# ls
aa.sh
[root@node1 v1]# cat aa.sh
hello jerry
[root@node1 v1]#
提示:-v指定宿主机目录:容器目录表示把宿主机目录挂载到容器的某个目录;容器里的目录可以是不存在的目录,它会自动创建;这种数据卷我们叫做bind-mount类型的数据卷;通常表现形式就是用户自己定义把宿主机的那个目录当作数据卷挂载到容器里的某个目录;和上面一样我们在宿主机上的对应目录下创建文件,在容器对应目录是可以正常访问到该文件的;-v可使用多次来指定不同的数据卷挂载关系;通常bind-mount类型的卷用的比较多;
示例:多个容器的卷使用同一宿主机目录
[root@node1 ~]# ll /hostdir/v1/aa.sh
-rw-r--r-- 1 root root 12 May 24 13:59 /hostdir/v1/aa.sh
[root@node1 ~]# cat /hostdir/v1/aa.sh
hello jerry
[root@node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@node1 ~]# docker run --name m1 -d -v /hostdir/v1/:/var/www/web/html linux1874/myimg:v0.1
9eb3287e4007f0656b1f099aac9504724307679ac41689774059388a96d75cf0
[root@node1 ~]# docker container inspect -f {{.Mounts}} m1
[{bind /hostdir/v1 /var/www/web/html true rprivate}]
[root@node1 ~]# docker container inspect -f {{.NetworkSettings.IPAddress}} m1
172.17.0.2
[root@node1 ~]# curl http://172.17.0.2
<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>
<BODY><H1>404 Not Found</H1>
The requested URL was not found
</BODY></HTML>
[root@node1 ~]# curl http://172.17.0.2/aa.sh
hello jerry
[root@node1 ~]# docker run --name m2 -d -v /hostdir/v1/:/var/www/web/html linux1874/myimg:v0.1
ff877e29d10c55b355b5270218d486894958880058e2eb7bef9bdd1c7c531f0f
[root@node1 ~]# docker container inspect -f {{.Mounts}} m2
[{bind /hostdir/v1 /var/www/web/html true rprivate}]
[root@node1 ~]# docker container inspect -f {{.NetworkSettings.IPAddress}} m2
172.17.0.3
[root@node1 ~]# curl http://172.17.0.3
<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>
<BODY><H1>404 Not Found</H1>
The requested URL was not found
</BODY></HTML>
[root@node1 ~]# curl http://172.17.0.3/aa.sh
hello jerry
[root@node1 ~]#
提示:数据卷挂载到容器会覆盖容器原有文件;这个同mount挂载没有本质的不同;从上面信息可以看到aa.sh就把原有的index.html给覆盖了;除了以上方式指定挂载同一宿主机目录外,我们还可以使用--volumes-from选项来指定从那个容器里复制数据挂载到本容器;如下
[root@node1 ~]# docker run --name m3 -d --volumes-from m1 linux1874/myimg:v0.1
61a1fbdc9c559a594870dc1e2bbf505a4eb588fc03e5ab50233b55b907beb9b0
[root@node1 ~]# docker container inspect -f {{.Mounts}} m3
[{bind /hostdir/v1 /var/www/web/html true rprivate}]
[root@node1 ~]# docker container inspect -f {{.NetworkSettings.IPAddress}} m3
172.17.0.4
[root@node1 ~]# curl http://172.17.0.4/aa.sh
hello jerry
[root@node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
linux1874/myimg v0.1 e408b1c6e04f 38 hours ago 1.22MB
busybox latest 78096d0a5478 10 days ago 1.22MB
centos 7 b5b4d78bc90c 2 weeks ago 203MB
nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB
[root@node1 ~]# docker run --name c1 -it --volumes-from m1 centos:7 /bin/sh
sh-4.2# ls /
anaconda-post.log dev home lib64 mnt proc run srv tmp var
bin etc lib media opt root sbin sys usr
sh-4.2# cat /var/www/web/html/aa.sh
hello jerry
sh-4.2#
示例:以只读方式挂载数据卷
[root@node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
linux1874/myimg v0.1 e408b1c6e04f 38 hours ago 1.22MB
busybox latest 78096d0a5478 10 days ago 1.22MB
centos 7 b5b4d78bc90c 2 weeks ago 203MB
nginx stable-alpine ab94f84cc474 4 weeks ago 21.3MB
[root@node1 ~]# docker run --name c1 -it -v /hostdir/v1/:/mydata:ro centos:7 /bin/sh
sh-4.2# ls /
anaconda-post.log dev home lib64 mnt opt root sbin sys usr
bin etc lib media mydata proc run srv tmp var
sh-4.2# cd mydata/
sh-4.2# ls
aa.sh
sh-4.2# echo "hello tom" > aa.sh
sh: aa.sh: Read-only file system
sh-4.2# exit
exit
[root@node1 ~]# docker run --name c2 -it -v /hostdir/v1/:/mydata centos:7 /bin/sh
sh-4.2# cd /mydata/
sh-4.2# ls
aa.sh
sh-4.2# echo "hello tom" > aa.sh
sh-4.2# cat aa.sh
hello tom
sh-4.2# exit
exit
[root@node1 ~]#
提示:我们挂载数据卷不指定权限默认是rw,以读写方式挂载;指定权限为ro(只读)挂载数据卷后,在容器内部就不能修改数据卷里的文件内容了;
示例:利用容器备份另一容器的数据
[root@node1 ~]# ll /hostdir/v1/
total 4
-rw-r--r-- 1 root root 10 May 24 14:42 aa.sh
[root@node1 ~]# echo "hello world" > /hostdir/v1/bb.sh
[root@node1 ~]# echo "hello world,hello tom" > /hostdir/v1/cc.sh
[root@node1 ~]# ls /hostdir/v1/
aa.sh bb.sh cc.sh
[root@node1 ~]# docker run --name m1 -d -v /hostdir/v1/:/var/www/web/html linux1874/myimg:v0.1
5959e832c01f68c24e2542138a95eb7bfeabcb7608b070ef1b536c625ddfd612
[root@node1 ~]# docker run --name c1 --volumes-from m1 -v $(pwd):/backup centos:7 tar cvf /backup/backup.tar.gz /var/www/web/html
tar: Removing leading `/' from member names
/var/www/web/html/
/var/www/web/html/aa.sh
/var/www/web/html/bb.sh
/var/www/web/html/cc.sh
[root@node1 ~]# ls
backup.tar.gz
[root@node1 ~]# tar xf backup.tar.gz
[root@node1 ~]# ls
backup.tar.gz var
[root@node1 ~]# cd var/www/web/html/
[root@node1 html]# ls
aa.sh bb.sh cc.sh
[root@node1 html]# cat aa.sh bb.sh cc.sh
hello tom
hello world
hello world,hello tom
[root@node1 html]#
提示:解释下上面利用容器备份另一容器里的数据;首先通过--volumes-from来克隆m1的数据卷,然后在通过-v来指定把当前路径挂载到容器内部的/backup目录下,然后通过启动容器执行tar cvf /backup/backup.tar.gz /var/www/web/html来把容器里的/var/www/web/html的文件打包到/backup/backup.tar.gz(容器内部的目录);能够在当前目录看到打包的文件原因是因为我们把当前路径挂载到容器里的/backup目录,所以我们在当前宿主机目录能够看到打包好的文件;
示例:利用容器恢复刚才打包的数据文件
首先运行一个容器
[root@node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5959e832c01f linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 15 minutes ago Up 15 minutes m1
[root@node1 ~]# docker run --name m2 -it -v /var/www/web/html linux1874/myimg:v0.1 /bin/sh
/ # ls /var/www/web/html/
index.html
/ # [root@node1 ~]#
然后在来一容器克隆之前容器的数据卷,通过挂载当前目录为数据卷,在执执行 tar xf命令来解包
[root@node1 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6462f22e0d7f linux1874/myimg:v0.1 "/bin/sh" 2 minutes ago Up 2 minutes m2
5959e832c01f linux1874/myimg:v0.1 "/bin/sh -c '/bin/ht…" 22 minutes ago Up 21 minutes m1
[root@node1 ~]# docker run --name c2 --volumes-from m2 -v $(pwd):/backup centos:7 tar xf /backup/backup.tar.gz
[root@node1 ~]# docker attach m2
/ # ls
bin dev etc home proc root sys tmp usr var
/ # ls /var/www/web/html/
aa.sh bb.sh cc.sh index.html
/ # cd /var/www/web/html/
/var/www/web/html # cat aa.sh bb.sh cc.sh
hello tom
hello world
hello world,hello tom
/var/www/web/html #
提示:以上命令的思想是运行容器C2 把m2的数据卷挂载先克隆到c2上,然后通过挂载当前宿主机目录到容器的/backup,然后再执行解包操作即可;这里还需要注意一点,如果容器的工作目录不是根目录或者是其他特殊目录,解压命令可以通过-C来指定解压到那个目录;
容器技术之Docker数据卷的更多相关文章
- docker 数据卷之进阶篇
笔者在<Docker 基础 : 数据管理>一文中介绍了 docker 数据卷(volume) 的基本用法.随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强.本文将在前 ...
- docker 数据卷 ---- 进阶篇
笔者在<Docker 基础 : 数据管理>一文中介绍了 docker 数据卷(volume) 的基本用法.随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强.本文将在前 ...
- Docker 数据卷与容器互联
Docker是基于Go语言实现的开源容器项目,Docker让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制, ...
- docker数据卷技术
数据卷技术 数据卷手动挂载 数据卷容器 part1:数据卷挂载方式 数据卷手动挂载 -v 主机目录:容器目录 #核心参数 #示例 docker run -it --name=centos_test - ...
- Docker 数据卷容器
如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器. 数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的. 首先,创建一个命名的数据卷容器 dbdata: $ sud ...
- docker 数据卷和docker数据卷容器以及数据卷的备份和还原
一:数据卷 1.什么是数据卷 数据卷是通过特殊设计的目录,可以绕过联合文件系统,为一个或者多个容器提供服务,数据卷是在docker宿主机当中,数据卷可以是文件也可以是文件夹. 2.特点 1.数据卷在容 ...
- 聊聊Docker数据卷和数据卷容器
当程序在容器运行的时候,特别是需要与其他容器中的程序或容器外部程序进行沟通交流,这时需要进行数据交换,作为常用的两种沟通数据的方式,网络通信与文件读写是需要提供给程序的支持, [数据卷] 文件是数据持 ...
- Docker容器学习梳理 - Volume数据卷使用
之前部署了Docker容器学习梳理--基础环境安装,接下来看看Docker Volume的使用. Docker volume使用 Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker ...
- Docker数据卷容器
用户需要在多个容器之间共享一些数据,就可以使用数据卷容器 从阿里云仓库下载镜像(也可以自己制作一个基础进项,比如只有几M的alpine) sudo docker pull registry.cn- ...
随机推荐
- mybatis源码学习(二):SQL的执行过程
从上一篇文章中,我们了解到MapperMethod将SQL的执行交给了sqlsession处理.今天我们继续往下看处理的过程. SqlSession接口除了提供获取Configuration,Mapp ...
- 数学--数论--HDU 2197 本原串 (推规律)
由0和1组成的串中,不能表示为由几个相同的较小的串连接成的串,称为本原串,有多少个长为n(n<=100000000)的本原串? 答案mod2008. 例如,100100不是本原串,因为他是由两个 ...
- 网络流--最大流--EK模板
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #i ...
- java基础知识备忘
1.java内存分配 a.寄存器cup -- 暂不涉及 b.本地方法栈 -- 虚拟机调用windows功能用的,比如创建文件夹 c.方法区 -- 存放 .class文件,负责存放方法 d.栈 -- ...
- Jmeter-接口测试参数化后循环断言不同内容的方法
前言 各位小伙伴在做接口自动化有没遇到过这样的问题,CSV文件参数化测试数据后,只能通过人工的的方法去查看结果,不懂写代码去循环断言返回的结果.今天我们来学习一下,不用写代码,就用响应断言,怎么实现循 ...
- G - Island Transport 网络流
题目: In the vast waters far far away, there are many islands. People are living on the islands, and a ...
- (三)Redis &分布式锁
1 Redis使用中的常见问题和解决办法 1.1 缓存穿透 定义:缓存系统都是按照key去缓存查询,如果不存在对应的value,就应该去DB查找.一些恶意的请求会故意查询不存在的key,请求量很大,就 ...
- Coursera课程笔记----C程序设计进阶----Week 5
指针(二) (Week 5) 字符串与指针 指向数组的指针 int a[10]; int *p; p = a; 指向字符串的指针 指向字符串的指针变量 char a[10]; char *p; p = ...
- 自己动手写RPC
接下来2个月 给自己定个目标 年前 自己动手做个RPC 框架 暂时技术选型 是 dotcore + netty + zookeeper/Consul
- 【Kafka】配置文件说明
目录 server.properties producer.properties consumer.properties server.properties # broker的全局唯一编号,不能重复 ...