Docker数据卷的使用

一、分层原理

在前面介绍过 ,镜像是一层层叠加而来,是只读不可修改的。最上面的一层称为“容器层”,是由镜像启动时,被添加的一层,我们的任何修改都会被记录在该容器层,而其它部分称为“镜像层”,都是只读不可修改的。镜像层的最下面我们称之为基础镜像(Base),大致的结构示意图如下所示。

镜像分层示意图

分层的好处就是可以共享资源,比如多个镜像都由某个Base镜像构建而来,那么在下载这些镜像的时候,Base镜像就可以共享使用,只需要下载一份,只需要保存一份Base镜像即可。除此之外,分层所体现的最大特性就是Copy-on-Write

  • 所有镜像的目录和文件会被组合成一个大的视图呈现在容器层,如果存在同名的,那么上层会覆盖下层的内容;
  • 增加新的数据会被直接放在最上层的容器层进行保存,镜像层不会被修改;
  • 尝试修改镜像层的数据会先从镜像层将数据copy到容器层,然后进行修改并保存在容器层,镜像层的数据不会被修改;

二、数据卷介绍

  • What?

    Data Volume本质上是宿主机上的文件或者目录,我们可以把它挂载到容器内部的文件系统中,使得宿主机和容器能够共享数据卷中的内容。

  • Why?

    容器中的数据在容器被销毁时也就消失了,在很多业务场景中这是不被允许的,比如数据库、日志系统、数据分析结果等,希望能将容器和存储分离开,容器即便销毁了,存储的数据依然存在。

    多个容器之间也有数据共享的需求,只要还有一个容器存在,共享的数据就不应该被清除;

  • How?

    常见的数据卷挂载主要有两种方式:命令挂载、使用DockerFile挂载,这两种方式都将在下面详细介绍。

三、命令挂载

3.1 指定路径挂载

所谓指定路径,是指同时指定了宿主机和容器内的挂载路径。

docker run -d -p 80:80 --name nginx01 -v E:\docker\nginx:/usr/nginx nginx

如上命令是在创建并启动容器的时候就进行目录的挂载,-d表示后台启动,-p 80:80表示绑定宿主机和容器的端口映射,--name nginx01表示指定新建的容器名称指定为nginx01,-v local_path:container_path表示挂载目录,将宿主机的路径local_path和容器内的路径container_path镜像挂载。

执行完成后,我们可以进入容器进行验证:

# pwd
/
# ls
bin   dev                  docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc                   lib   media  opt  root  sbin  sys  usr
# cd usr
# ls
bin  games  include  lib  libexec  local  nginx  sbin  share  src
# cd nginx
# ls
#

可以看到,容器内部的/usr/nginx目录已经存在,但是里面没有任何内容。现在我们在宿主机上或者在容器内的挂载目录内创建一个文件,在另外一边都能同步看到。

# pwd
/
# ls
bin   dev                  docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc                   lib   media  opt  root  sbin  sys  usr
# cd usr
# ls
bin  games  include  lib  libexec  local  nginx  sbin  share  src
# cd nginx
# ls
# ls
readme.txt
# cat readme.txt
hello docker volume!#

我们此时将容器删除:docker rm nginx01,然后在宿主机的挂载目录下发现,文件依然存在,并没有随着容器的移除而删除 。

需要注意的是:

  • 在进行目录挂载的时候,要求宿主机中的文件或路径已经存在,而容器内则不作要求;
  • 已经挂载的路径,本质上是容器把宿主机路径或者文件进步同步copy,而非引用的关系,所以同一目录或者文件是占用两倍存储空间;
  • 可以在容器路径后加上:ro表示该路径容器只允许只读权限,或者加上:rw表示该路径容器拥有读写权限(默认);

指定路径挂载当然存在一定的缺陷,比如我们指定了宿主机的挂载路径,就不利于容器的移植了 ,A宿主机有这个挂载路径,B宿主机也许就没有 。

3.2 匿名挂载

docker run -d -p 80:80 --name nginx2 -v /usr/nginx02 nginx

该命令与指定目录挂载的区别是-v /usr/nginx02只是指定了容器内的挂载路径,并未指定宿主机的挂载路径。我们可以通过docker inspect name来查看容器的详细信息得到具体宿主机的挂载路径:

"Mounts": [
    {
        "Type": "volume",
        "Name": "592c56295f0200cb62b5f226cba1f53c77e45b48a95c77b6ce791c9b05696cc7",
        "Source": "/var/lib/docker/volumes/592c56295f0200cb62b5f226cba1f53c77e45b48a95c77b6ce791c9b05696cc7/_data",
        "Destination": "/usr/nginx02",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]

如上Source中的路径就是宿主机上的挂载路径,Destination是容器内的挂载路径。我们注意到卷名目录是一串无意义的数字字母组合,因此称为匿名挂载。

问题:以上挂载路径在windows系统的哪里尚未找到,有知道的可以帮忙补充下。

3.3 具名挂载

所谓具名就是指给无意义的数据卷起名字,挂载的格式和指定路径挂载一致 :

docker run -d -p 80:80 --name nginx3 -v nginx_volume:/usr/nginx03 nginx

此时 ,数据卷的名称就是我们指定的nginx_volume,而不是无意义的数字字母组合了。

注意:

  • 数据卷如果被容器使用中是不能被删除的,需要先删除容器后,才可以删除数据卷;
  • 可以通过多个-v同时指定多个挂载路径;

四、共享数据

在前面的例子中,我们已经实现了宿主机挂载路径和容器内挂载路径的数据共享,下面就数据共享进行更深一步地探讨。

场景一:多个容器组成的集群需要共享宿主机的数据。

按照如上的使用说明,我们同时为多个容器挂载到宿主机的同一目录或者文件即可:

docker run -d -p 80:80 --name nginx01 -v E:\docker\nginx:/usr/nginx nginx
docker run -d -p 81:81 --name nginx02 -v E:\docker\nginx:/usr/nginx nginx
docker run -d -p 82:82 --name nginx03 -v E:\docker\nginx:/usr/nginx nginx

但是有一个缺点,一旦我们要修改宿主机的挂载目录,需要对每一个容器的挂载关系进行修改,显然不方便。此时我们就需要抽象一层容器出来,使得只有该容器和宿主机的挂载点绑定,其它容器和该容器绑定,这种容器我们称之为“数据卷容器”,Volume Container,简称VC容器。

docker create --name vc_data -v volume_name:container_path image_name
docker run -d -p 80:80 --name nginx01 --volumes-from  vc_data nginx
docker run -d -p 81:81 --name nginx02 --volumes-from  vc_data nginx
docker run -d -p 82:82 --name nginx03 --volumes-from  vc_data nginx

如此,nginx01、nginx02、nginx03这三个容器就继承了vc_data数据卷容器的数据卷信息,使得它们和宿主机的挂载路径绑定了对应关系。随后只要修改vc_data的挂载关系,nginx01~nginx03就能自动更改,体现了编程领域的继承和解耦的优势。

场景二:多个容器组成的集群相互之间共享数据

这种场景就是不涉及宿主机的文件了,容器之间的数据不需要和宿主机进行共享。我们在创建镜像的时候就把数据封装到了镜像里面,并且建立了数据卷。

FROM busybox:latest
ADD readme.md /usr/file
VOLUME /usr/file

如上的dockerfile指定了数据卷就是容器的usr/file目录,然后基于该dockerfile构建镜像并创建容器:

docker build -t new_image .
docker create --name vc_data new_image

如此新创建的vc_data就是容器卷镜像,它不需要运行,只是共享数据而已。

docker run -d -p 80:80 --name nginx01 --volumes-from  vc_data nginx
docker run -d -p 81:81 --name nginx02 --volumes-from  vc_data nginx
docker run -d -p 82:82 --name nginx03 --volumes-from  vc_data nginx

如此,就能实现容器之间数据卷的共享。需要注意的是,只要任何一个容器仍然存在,那么该数据卷就不会被删除,只有当所有使用该数据卷的容器都删除了,数据卷才会被删除。

五、DockerFile挂载

在后面的内容中我们会介绍Dockerfile的使用,其中也可以在新镜像的制作时就进行数据卷的挂载,比如:

FROM java:8
VOLUME ["/tmp","/home/docker/demo"]
...

其中,VOLUME指令就是进行数据卷挂载,后面的参数是容器中需要挂载的路径,但是只能进行匿名挂载。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352

推荐阅读更多精彩内容