docker存储卷的使用

COW技术原理(Copy On Write,写时复制)

Ø 直接映射原始盘的数据内容

Ø 当原始盘的旧数据有修改时,在修改之前自动将旧数据存入前端盘

Ø 对前端盘的修改不回写到原始盘

Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。

如果运行中的容器修改了现有的一个已经存在的文件,那么该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本依然存在,只是已经被读写层中该文件的副本所隐藏,这就是“写时复制(COW)”机制。
在这里插入图片描述

 示例

[root@localhost ~]# docker run -it --name b1 --rm busybox /bin/sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # mkdir data
/ # echo 'hello world' > data/index.htlm
//先启动一个容器 创建一个目录


[root@localhost ~]# docker commit -a 'sean <1@2.com>' -c 'CMD ["/bin/sh"]' -p b1 busybox:v0.1
sha256:df9c91d328620ab63efee4f645d9b7ef90890f2b808f38f048cb36910646cd3f
[root@localhost ~]# docker run -it --name b2 busybox:v0.1
/ # 
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # ls data/
index.htlm
/ # 
/ # rm -rf data
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # 
//在另一个终端打开删除

[root@localhost ~]# docker run -it --name b1 --rm busybox /bin/sh
/ # ls
bin   dev   etc   home  proc  root  sys   tmp   usr   var
/ # mkdir data
/ # echo 'hello world' > data/index.htlm
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # 
//再回到第一个终端查看并没有删除 ,只是被隐藏

对于这种方式来说,我们去访问一个文件,修改和删除等一类的操作,其效率会非常的低,因为隔着很多层镜像。

而要想绕过这种限制,我们可以通过使用存储卷的机制来实现。

使用存储卷的好处

容器中进程所生成的数据,都保存在存储卷上,从而脱离容器文件系统自身后,当容器被关闭甚至被删除时,都不用担心数据被丢失,实现数据可以脱离容器生命周期而持久,当再次重建容器时,如果可以让它使用到或者关联到同一个存储卷上时,再创建容器,虽然不是之前的容器,但是数据还是那个数据,特别类似于进程的运行逻辑,进程本身不保存任何的数据,数据都在进程之外的文件系统上,或者是专业的存储服务之上,所以进程每次停止,只是保存程序文件,对于容器也是一样;容器就是一个有生命周期的动态对象来使用,容器关闭就是容器删除的时候,但是它底层的镜像文件还是存在的,可以基于镜像再重新启动容器。

但是容器有一个问题,一般与进程的启动不太一样,就是容器启动时选项比较多,如果下次再启动时,很容器会忘记它启动时的选项,所以最好有一个文件来保存容器的启动,这就是容器编排工具的作用。一般情况下,是使用命令来启动操作docker,但是可以通过文件来读,也就读文件来启动,读所需要的存储卷等,但是它也只是操作一个容器,这也是需要专业的容器编排工具的原因。

另一个优势就是容器就可以不置于启动在那台主机之上了,如几台主机后面挂载一个NFS,在各自主机上创建容器,而容器上通过关联到宿主机的某个目录上,而这个目录也是NFS所挂载的目录中,这样容器如果停止或者是删除都可以不限制于只能在原先的宿主机上启动才可以,可以实现全集群范围内调试容器的使用,当再分配存储、计算资源时,就不会再局限于单机之上,可以在集群范围内建立起来,基本各种docker的编排工具都能实现此功能,但是后面严重依赖于共享存储的使用。
 

为什么要用存储卷

关闭重启容器,数据不受影响。但是删除docker容器,则其更改会全部丢失

因此docker存在的问题有:

        1 存储与联合挂在文件系统中,不宜与宿主机访问

        2 容器间数据共享不便

        3 删除容器其数据会丢失

而要解决以上的问题就是要是有存储卷

存储卷管理

“卷”是容器上的一个或多个“目录”,此类目录可绕过联合文件系统,与宿主机上的某个目录“绑定(关联)”;

类似于挂载一样,宿主机的/data/web目录与容器中的/container/data/web目录绑定关系,然后容器中的进程向这个目录中写数据时,是直接写在宿主机的目录上的,绕过容器文件系统与宿主机的文件系统建立关联关系,使得可以在宿主机和容器内共享数据库内容,让容器直接访问宿主机中的内容,也可以宿主机向容器供集内容,两者是同步的。

mount名称空间本来是隔离的,可以让两个本来是隔离的文件系统,在某个子路径上建立一定程度的绑定关系,从而使得在两个容器之间的文件系统的某个子路径上不再是隔离的,实现一定程度上共享的效果。
在这里插入图片描述

 在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。

容器数据的管理

用户在使用docker的 过程中,往往需要查看容器内应用产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间数据共享,这必然涉及到容器数据的管理操作。

容器中数据管理主要有2种方式:

1 数据卷 (DaTa Volumes)

2 数据卷容器(DaTa Volumes Containers)

容器Volumes使用语法:

Docker Managed Volume

示例,没绑定过的卷

[root@localhost ~]# docker run -it --rm --name b1 -v /data busybox /bin/sh
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # 
//创建一个容器

"Mounts": [
            {
                "Type": "volume",
                "Name": "af5b3e55d185ab66e6f06ee177c544984ee56938e58bc635c728ae8aec0429e1",
                "Source": "/var/lib/docker/volumes/af5b3e55d185ab66e6f06ee177c544984ee56938e58bc635c728ae8aec0429e1/_data",
                "Destination": "/data",
//查看位置


[root@localhost ~]# cd /var/lib/docker/volumes/af5b3e55d185ab66e6f06ee177c544984ee56938e58bc635c728ae8aec0429e1/_data
[root@localhost _data]# ls
[root@localhost _data]# touch abc
[root@localhost _data]# ls
abc
//进入这个路径写一个目录去容器查看

[root@localhost ~]# docker run -it --rm --name b1 -v /data busybox /bin/sh
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # cd data/
/data # ls
abc
/data # 
/ # rm -f data/abc
/ # exit 
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
//删掉之后去另一边查看

[root@localhost _data]# ls
[root@localhost _data]# 
//也随之删掉

示例2 绑定之后的卷

[root@localhost ~]# docker run -it --rm --name b1 -v /web:/data busybox
/ # ls
bin   data  dev   etc   home  proc  root  sys   tmp   usr   var
/ # ls data/
/ # 
//创建一个容器绑定一个web

[root@localhost ~]# ls /
bin   dev  home        lib    media  opt   root  sbin  sys  usr  web
boot  etc  index.htlm  lib64  mnt    proc  run   srv   tmp  var
//在真机上系统会自动创建一个web

[root@localhost ~]# cd /web
[root@localhost web]# ls
[root@localhost web]# echo  'hello world' > index.htlm
//进入web创建一个文件

/ # cd data/
/data # ls
index.htlm
//此时容器里面也会同步


/data # exit
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
//退出删除后去web查看文件是否存在

[root@localhost web]# ls
index.htlm

[root@localhost ~]#  docker run -it --rm --name b1 -v /web:/data busybox
/ # ls data/
index.htlm
/ # 
//可以看见删除之后和重新创建之后文件依然存在

用存储卷部署网站

[root@localhost web]# mv ~/123.zip .
[root@localhost web]# ls
123.zip
[root@localhost web]# unzip 123.zip 
Archive:  123.zip
  inflating:   ┼▄┐с╒╧░н╠°╘╛╨б╙╬╧╖╥╗╕Ў╢╝▓╗─▄╦└HTML5═°╥│╨б╙╬╧╖┤·┬ы╧┬╘╪-╙╬╧╖╘┤┬ы-╦╪▓─╦╡├ў.txt  
   creating: 38234/images/
  inflating: 38234/images/gdyx.png   
  inflating: 38234/images/wu.png     
  inflating: 38234/images/xiaoren.png  
  inflating: 38234/images/ygdbns.jpg  
  inflating: 38234/index.html        
   creating: 38234/js/
  inflating: 38234/js/main.js        
  inflating: 38234/js/require.js     
  inflating: ╘┤┬ы╦╪▓─├т╖╤╧┬╘╪.url  
  inflating: ░о╕°═°-╘┤┬ы-├т╖╤╧┬╘╪.txt  
//解压

[root@localhost web]# ls
 123.zip
 38234
 images
 index.html
 js

[root@localhost web]# rm -rf 123.zip/ 38234
[root@localhost web]# ls
 123.zip
 images
 index.html
 js

写一个httpd的网站

[root@localhost ~]# docker run -d --name web -v /web:/usr/local/apache2/htdocs -p 80:80 httpd
11daaf56faf553395a2a604b5e8bba4e2e85f96a2be4b52c4135bdeb83e4f6f0

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED          STATUS          PORTS                               NAMES
11daaf56faf5   httpd     "httpd-foreground"   37 seconds ago   Up 36 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   web
[root@localhost ~]# ss -ant
State    Recv-Q   Send-Q     Local Address:Port     Peer Address:Port    Process   
LISTEN   0        128              0.0.0.0:80            0.0.0.0:*                 
LISTEN   0        128              0.0.0.0:22            0.0.0.0:*                             
LISTEN   0        128                 [::]:80               [::]:*                 
LISTEN   0        128                 [::]:22               [::]:*      

接下来访问网站

 只读挂载,不影响网站访问

[root@localhost ~]# docker rm -f web
web
[root@localhost ~]# docker run -d --name web -v /web:/usr/local/apache2/htdocs:ro -p 80:80 httpd
ff5a103f26616b2ca45a657d80f97cbd1c2958ba17bbf9100a308f2ee10508ab

 

root@ff5a103f2661:/usr/local/apache2/htdocs# touch  abc
touch: cannot touch 'abc': Read-only file system
/此时在网站里面创建文件不行

[root@localhost web]# touch abc
root@ff5a103f2661:/usr/local/apache2/htdocs# ls
123.zip
 abc
 images
 index.html
 js
//在外创建里面可一查看。

数据卷容器

如果用户需要在容器之间共享一些持续更新的数据,最简单的方式就是使用数据卷容器。数据卷容器就是一个普通的容器,专门用他提供数据卷供其他容器挂载使用。方法如下:

创建一个dbdata的容器

[root@localhost ~]# docker run -itd --name dbdata -v /dbdata busybox
0d0d4a72659439e16fd24e848cac4cbc928d21989ba265092d6c6b5eec24ba69
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS         PORTS     NAMES
0d0d4a726594   busybox   "sh"      5 seconds ago   Up 4 seconds             dbdata

然后使用Volumes from来挂载dbdata容器中的数据卷

[root@localhost ~]# docker run -itd --name db1 --volumes-from dbdata busybox
878ab7c72adac6d321b70556688cc637f54e1283357b92d643fca7e55c078a0b
[root@localhost ~]# docker run -itd --name db2 --volumes-from dbdata busybox
af6eeef0a534cba93547d0948f4f54db590e2dd7fffd8e7ee3adae8a4a6bdbc0
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
af6eeef0a534   busybox   "sh"      5 seconds ago    Up 4 seconds              db2
878ab7c72ada   busybox   "sh"      39 seconds ago   Up 39 seconds             db1
0d0d4a726594   busybox   "sh"      4 minutes ago    Up 4 minutes              dbdata

此时可以发现在db1上创建文件可以在db2上看到

[root@localhost ~]# docker exec -it db1 /bin/sh
/ # ls
bin     dev     home    root    tmp     var
dbdata  etc     proc    sys     usr
/ # cd dbdata/
/dbdata # touch abc
/dbdata # ls
abc


[root@localhost ~]# docker exec -it db2 /bin/sh
/ # ls dbdata/
abc
[root@localhost ~]# docker run -itd --name db3 --volumes-from dbdata busybox
8ead6bdc4f8ed225cbcb1b735bd8fe9c171f7fd1e4f7f7da49437ccab2f52018

[root@localhost ~]# docker exec -it db3 /bin/sh
/ # cd dbdata/
/dbdata # ls
/dbdata # echo 'hello world' > abc
/dbdata # ls
abc
/dbdata # cat abc
hello world

[root@localhost ~]# docker exec -it dbdata /bin/sh
/ # ls dbdata/
abc
/ # cat dbdata/abc
hello world

使用-V删除建立关系的容器,必须全部删掉

[root@localhost ~]# docker exec -it db3 /bin/sh
/ # cd dbdata/
/dbdata # ls
abc
//进入db3

[root@localhost ~]# cd /var/lib/docker/volumes/68731bf3053b730a1e5d4593ab4917943515af52a11c09bde72d3aba97d7fbc3/_data
[root@localhost _data]# ls
abc
//文件在路径中

[root@localhost ~]# docker rm -f db3
db3
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
//删掉db3

[root@localhost _data]# ls
abc
//文件还在

使用-V才能完全删除

利用数据卷迁移数据

[root@localhost ~]# docker run --name worker --volumes-from dbdata -v $(pwd):/backup centos tar cvf /backup/backup.tar /dbdata

用centos镜像创建一个worker容器,使用--volumes-from让worker容器挂载到dbdata的数据卷‘。

使用-v $(pwd):/backup参数来挂在本地当前目录到worker容器的backup目录。

worker容器启动后使用 tar cvf /backup/backup.tar /dbdata命令将dbdata下内容备份为容器内的/backup/backup.tar,寄宿住机当前目录的backup.tar

恢复

[root@localhost ~]# docker -it --name dbdata2 -v /dbdata centos /bin/bash

然后在创建一个容器 挂载到dbdata2 使用untar解压到备份文件所挂载的容器卷即可

[root@localhost ~]# docker run --volumes-from dbdata2 -v $(pwd):/bakup busybox tar xvf /backup/backup.tar

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值