Docker存储卷篇

                                      作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

  

一.写时复制(COW)机制

所谓写时复制的效果如上图所示:
  Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层。
  如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本依然存在,只是已经被读写层中该文件的副本所隐藏,此即"读写复制(COW)"机制。

二.数据卷(Data Volume)概述

 1>.什么是存储卷(volume)

  关闭并重启容器,其数据不受影响;但删除Docker容器,则其更改将会全部丢失。原因就是我们上面提到的写时复制机制,这个写时复制机制存在于容器,数据默认都保存在容器内。

  Docker设计存在的问题:
    1>.存储于联合文件系统中,不易于宿主机访问;
    2>.容器间数据共享不便;
    3>.删除容器其数据会丢失;   解决方案:"存储卷(volume)"
    如下图所示:"卷"是容器上的一个或多个"目录",此类目录可绕过联合文件系统,于宿主机上的某个目录"绑定(关联)"

 2>.存储卷(volume)的作用

  1.数据卷为持久或共享数据提供了几个有用的特性:
    1>.Volume于容器(container)初始化之时即会创建,由base image提供的卷中的数据于此期间完成复制;
    2>.数据卷可以在容器之间共享和重用;
    3>.更新镜像(image)时不会包括对数据卷的更改;
    4>.即使容器(container)自身被删除,数据卷仍保持不变。   2.Volume的初衷是独立于容器的生命周期实现数据持久化:
    1>.默认情况下删除容器之时既不会删除卷,也不会对哪怕未被引用的卷做垃圾回收操作;
    2>.如果我们删除容器时使用了特殊的选项(类似于linux的"userdel -r"选项)也可以一并删除容器的存储卷,但是生成环境我们不会这样做。   3.卷为docker提供了独立于容器的数据管理机制(如下图所示):
    1>.可以把"镜像"想像成静态文件,例如"程序",把卷类比为动态内容,例如"数据";于是,镜像可以重用,而卷可以共享;
    2>.卷实现了"程序(镜像)"和"数据(卷)"分离,以及"程序(镜像)"和"制作镜像的主机"分离,用户制作镜像时无须再考虑镜像运行的容器所在的主机的环境;

 3>.docker存储卷类型(Volume types)

  如下图所示,Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同:
    1>.绑定挂载卷(Bind mount volume)
      指向主机文件系统上用户指定位置的卷。换句话说,在宿主机上的路径你需要人工指定一个特定路径,再容器上的路径也需要指定一个特定路径,让这两个已知路径建立关联关系。随着容器删除,存储卷数据并不会丢失。     2>.docker管理的卷(Docker managed volume)
      Docker守护进程在Docker拥有的主机文件系统的一部分中创建管理卷。换句话说,我们只需要在容器内指定挂载点是什么,而绑定的是宿主机哪个路径下的目录我们不需要管,由容器引擎的docker daemon自行创建一个空目录或者使用一个已存在目录与你的存储卷路径建立关联关系。随着容器删除,存储卷数据也随着丢失了。
  

三.在容器这种使用Volumes

1>.Docker managed volume案例

[root@node101.yinzhengjie.org.cn ~]# docker run --name c1 -it --rm busybox
/ # ls /
bin dev etc home proc root sys tmp usr var
/ #
/ # exit
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# docker run --name c1 -it -v /data --rm busybox      #注意,我们使用"-v"选项来指定c1容器内docker管理卷存放为位置,而具体对应宿主机的哪个路径我们无需关心,而是由docker daemon进程自行创建,我们可以通过相关命令查看对应的具体路径。
/ #
/ # ls /          #很上面的容器相比,很显然,咱们这个容器多出了一个"/data"目录,该目录即为docker managed volume实例。
bin data dev etc home proc root sys tmp usr var
/ #
[root@node101.yinzhengjie.org.cn ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d574ca3e42a6 busybox "sh" minutes ago Up minutes c1
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# docker inspect c1 #查看c1容器的详细信息,注意观察keys为"Mounts"的"Source"属性对应的值,它所指向的路径就是c1容器"/data"目录所在宿主机的存储路径。
[
{
"Id": "d574ca3e42a6cc08e009ba44b3c7bcd467362ff10c71d9461211a7e9687e2c09",
"Created": "2019-10-19T01:12:06.848411027Z",
"Path": "sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": ,
"ExitCode": ,
"Error": "",
"StartedAt": "2019-10-19T01:12:07.402652338Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:19485c79a9bbdca205fce4f791efeaa2a103e23431434696cc54fdd939e9198d",
"ResolvConfPath": "/var/lib/docker/containers/d574ca3e42a6cc08e009ba44b3c7bcd467362ff10c71d9461211a7e9687e2c09/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/d574ca3e42a6cc08e009ba44b3c7bcd467362ff10c71d9461211a7e9687e2c09/hostname",
"HostsPath": "/var/lib/docker/containers/d574ca3e42a6cc08e009ba44b3c7bcd467362ff10c71d9461211a7e9687e2c09/hosts",
"LogPath": "/var/lib/docker/containers/d574ca3e42a6cc08e009ba44b3c7bcd467362ff10c71d9461211a7e9687e2c09/d574ca3e42a6cc08e009ba4
4b3c7bcd467362ff10c71d9461211a7e9687e2c09-json.log", "Name": "/c1",
"RestartCount": ,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount":
},
"AutoRemove": true,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": ,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": ,
"Runtime": "runc",
"ConsoleSize": [
, ],
"Isolation": "",
"CpuShares": ,
"Memory": ,
"NanoCpus": ,
"CgroupParent": "",
"BlkioWeight": ,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": ,
"CpuQuota": ,
"CpuRealtimePeriod": ,
"CpuRealtimeRuntime": ,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": ,
"KernelMemoryTCP": ,
"MemoryReservation": ,
"MemorySwap": ,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": ,
"CpuPercent": ,
"IOMaximumIOps": ,
"IOMaximumBandwidth": ,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/b91e241fd4070485ceb246e18c2d258df9666797453448b287e4253e6a5bc437-init/diff:/var/l
ib/docker/overlay2/ead7a29001855b8898300b67763a050eeb50e5c7988076f4777b56e85365169e/diff", "MergedDir": "/var/lib/docker/overlay2/b91e241fd4070485ceb246e18c2d258df9666797453448b287e4253e6a5bc437/merged",
"UpperDir": "/var/lib/docker/overlay2/b91e241fd4070485ceb246e18c2d258df9666797453448b287e4253e6a5bc437/diff",
"WorkDir": "/var/lib/docker/overlay2/b91e241fd4070485ceb246e18c2d258df9666797453448b287e4253e6a5bc437/work"
},
"Name": "overlay2"
},
"Mounts": [
{
"Type": "volume",
"Name": "3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914",
"Source": "/var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data",        #注意观察这里,这就是我们c1容器"/data"存储卷对应的宿主机路径。
"Destination": "/data",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
"Config": {
"Hostname": "d574ca3e42a6",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"sh"
],
"Image": "busybox",
"Volumes": {
"/data": {}
},
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "7fcfdb3cbc2d42503fbd9f44d4c9606ee484cedc26d88f7c5c7a7934efb82be5",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": ,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/7fcfdb3cbc2d",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "d81e297a392c3f6c73422ddb016b9c126a8f50ace798920947d331cea3c9baa0",
"Gateway": "192.168.100.254",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": ,
"IPAddress": "192.168.100.1",
"IPPrefixLen": ,
"IPv6Gateway": "",
"MacAddress": "02:42:c0:a8:64:01",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "7ad23e4ff4b3bbaa8cea6b89507921beb407568e021f3dad666a829ec817be7e",
"EndpointID": "d81e297a392c3f6c73422ddb016b9c126a8f50ace798920947d331cea3c9baa0",
"Gateway": "192.168.100.254",
"IPAddress": "192.168.100.1",
"IPPrefixLen": ,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": ,
"MacAddress": "02:42:c0:a8:64:01",
"DriverOpts": null
}
}
}
}
]
[root@node101.yinzhengjie.org.cn ~]# cd /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data #我们进入到c1容器对应"/data"目录在宿主机的路径,就可以实现c1容器和宿主机数据共享。
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]#
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]# ls
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]#
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]# echo "hello container" >> test.html
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]#
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]# ls
test.html
[root@node101.yinzhengjie.org.cn /var/lib/docker/volumes/3fc67ccb38ce00fb1257950e77ad71b5b01fc0d53f6959eda1e810e970153914/_data]#

[root@node101.yinzhengjie.org.cn ~]# docker inspect c1  #查看c1容器的详细信息,注意观察keys为"Mounts"的"Source"属性对应的值,它所指向的路径就是c1容器"/data"目录所在宿主机的存储路径。

2>.Bind mount volume案例

[root@node101.yinzhengjie.org.cn ~]# docker run --name c1 -it  --rm busybox
/ #
/ # ls /
bin dev etc home proc root sys tmp usr var
/ #
/ # exit
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# docker run --name c1 -it -v /data/volumes/c1:/data2 --rm busybox      #和上面有所不同,我们手动指定宿主机"/data/volumes/c1"(该路径会自动创建)路径和c1容器的"/data2"路径建立关联关系
/ #
/ # ls /    #注意,和上面的容器相比,当前容器多出来了一个"/data2"目录,该目录是咱们手动指定的"bind mount volume"卷。
bin data2 dev etc home proc root sys tmp usr var
/ #
[root@node101.yinzhengjie.org.cn ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d6992f8321d busybox "sh" About a minute ago Up About a minute c1
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# docker inspect c1           #查看c1容器的详细信息,注意观察keys为"Mounts"的"Source"属性对应的值
[
{
"Id": "8d6992f8321d04bbab860550f9d48e9b37c8989052a6f671ebfbe66543f549ad",
"Created": "2019-10-19T01:30:45.806381621Z",
"Path": "sh",
"Args": [],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": ,
"ExitCode": ,
"Error": "",
"StartedAt": "2019-10-19T01:30:46.253664572Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:19485c79a9bbdca205fce4f791efeaa2a103e23431434696cc54fdd939e9198d",
"ResolvConfPath": "/var/lib/docker/containers/8d6992f8321d04bbab860550f9d48e9b37c8989052a6f671ebfbe66543f549ad/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/8d6992f8321d04bbab860550f9d48e9b37c8989052a6f671ebfbe66543f549ad/hostname",
"HostsPath": "/var/lib/docker/containers/8d6992f8321d04bbab860550f9d48e9b37c8989052a6f671ebfbe66543f549ad/hosts",
"LogPath": "/var/lib/docker/containers/8d6992f8321d04bbab860550f9d48e9b37c8989052a6f671ebfbe66543f549ad/8d6992f8321d04bbab86055
0f9d48e9b37c8989052a6f671ebfbe66543f549ad-json.log", "Name": "/c1",
"RestartCount": ,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "",
"ExecIDs": null,
"HostConfig": {
"Binds": [
"/data/volumes/c1:/data2"
],
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "default",
"PortBindings": {},
"RestartPolicy": {
"Name": "no",
"MaximumRetryCount":
},
"AutoRemove": true,
"VolumeDriver": "",
"VolumesFrom": null,
"CapAdd": null,
"CapDrop": null,
"Capabilities": null,
"Dns": [],
"DnsOptions": [],
"DnsSearch": [],
"ExtraHosts": null,
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": ,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": ,
"Runtime": "runc",
"ConsoleSize": [
, ],
"Isolation": "",
"CpuShares": ,
"Memory": ,
"NanoCpus": ,
"CgroupParent": "",
"BlkioWeight": ,
"BlkioWeightDevice": [],
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": ,
"CpuQuota": ,
"CpuRealtimePeriod": ,
"CpuRealtimeRuntime": ,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": [],
"DeviceCgroupRules": null,
"DeviceRequests": null,
"KernelMemory": ,
"KernelMemoryTCP": ,
"MemoryReservation": ,
"MemorySwap": ,
"MemorySwappiness": null,
"OomKillDisable": false,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": ,
"CpuPercent": ,
"IOMaximumIOps": ,
"IOMaximumBandwidth": ,
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/3b5c1e2681b83025782d55c671c56e94028d17febc0058e621fdb3d2816c3de8-init/diff:/var/l
ib/docker/overlay2/ead7a29001855b8898300b67763a050eeb50e5c7988076f4777b56e85365169e/diff", "MergedDir": "/var/lib/docker/overlay2/3b5c1e2681b83025782d55c671c56e94028d17febc0058e621fdb3d2816c3de8/merged",
"UpperDir": "/var/lib/docker/overlay2/3b5c1e2681b83025782d55c671c56e94028d17febc0058e621fdb3d2816c3de8/diff",
"WorkDir": "/var/lib/docker/overlay2/3b5c1e2681b83025782d55c671c56e94028d17febc0058e621fdb3d2816c3de8/work"
},
"Name": "overlay2"
},
"Mounts": [
{
"Type": "bind",
"Source": "/data/volumes/c1",
"Destination": "/data2",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Config": {
"Hostname": "8d6992f8321d",
"Domainname": "",
"User": "",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
],
"Cmd": [
"sh"
],
"Image": "busybox",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": null,
"Labels": {}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "5a5cc75df84d9544f2bcb17d7d155caac3bb70a850b44dd7a7dbafbe9affda69",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": ,
"Ports": {},
"SandboxKey": "/var/run/docker/netns/5a5cc75df84d",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "b67ad92c10b5d239071a18f43b17a14a06f15ac4e39bd82f6c0eb8285f1b56f2",
"Gateway": "192.168.100.254",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": ,
"IPAddress": "192.168.100.1",
"IPPrefixLen": ,
"IPv6Gateway": "",
"MacAddress": "02:42:c0:a8:64:01",
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID": "7ad23e4ff4b3bbaa8cea6b89507921beb407568e021f3dad666a829ec817be7e",
"EndpointID": "b67ad92c10b5d239071a18f43b17a14a06f15ac4e39bd82f6c0eb8285f1b56f2",
"Gateway": "192.168.100.254",
"IPAddress": "192.168.100.1",
"IPPrefixLen": ,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": ,
"MacAddress": "02:42:c0:a8:64:01",
"DriverOpts": null
}
}
}
}
]
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# ls /data/volumes/c1/
[root@node101.yinzhengjie.org.cn ~]#

[root@node101.yinzhengjie.org.cn ~]# docker inspect c1           #查看c1容器的详细信息,注意观察keys为"Mounts"的"Source"属性对应的值

[root@node101.yinzhengjie.org.cn ~]# docker inspect -f {{.Mounts}} c1                #我们不用获取c1的全部信息,比如我们只需要获取"Mounts"的概要属性。
[{bind /data/volumes/c1 /data2 true rprivate}]
[root@node101.yinzhengjie.org.cn ~]#
[root@node101.yinzhengjie.org.cn ~]# docker inspect -f {{.NetworkSettings.IPAddress}} c1     #同理,我们也可以按照这种方式取出其它咱们想要的信息
192.168.100.1
[root@node101.yinzhengjie.org.cn ~]#

四.共享卷(Sharing volumes)

1>.多个容器使用同一个存储卷案例(咱们试验只是使用两个容器,实际上只要资源充足的情况下你可以启动任意个容器共享存储卷)

[root@node101.yinzhengjie.org.cn ~]# docker run --name c1 -it -v /data/volumes/c1:/data --rm busybox      #我们创建一个C1容器,并在/data目录中写入测试数据,该容器不要停止它,在重新开启一个终端运行另外一个容器,来和c1容器共享存储卷数据。
/ #
/ # ls /
bin data dev etc home proc root sys tmp usr var
/ #
/ # ls /data/
/ #
/ # echo "<h1>docker container test</h1>" > /data/index.html
/ #
/ # ls /data/
index.html
/ #
/ #
/ # cat /data/index.html
<h1>docker container test</h1>
/ #

[root@node101.yinzhengjie.org.cn ~]# docker run --name c1 -it -v /data/volumes/c1:/data --rm busybox      #我们创建一个C1容器,并在/data目录中写入测试数据,该容器不要停止它,在重新开启一个终端运行另外一个容器,来和c1容器共享存储卷数据。

[root@node101.yinzhengjie.org.cn ~]# docker run --name c2 -it -v /data/volumes/c1:/data --rm busybox      #通过测试发现,c2和c1虽然不是同一个容器且各自由独立的用户空间,但它们却可以通过存储卷来实现数据共享。
/ #
/ # ls /
bin data dev etc home proc root sys tmp usr var
/ #
/ # ls /data/
index.html
/ #
/ # cat /data/index.html
<h1>docker container test</h1>
/ #

2>.复制使用其它容器的卷

[root@node101.yinzhengjie.org.cn ~]# docker run --name InfrastructureImage -it -v /data/InfrastructureImage/volumes:/data/web/html busybox    #此处启动一个基础镜像
/ #
/ # ls /
bin data dev etc home proc root sys tmp usr var
/ # / # ls /data/ -R
/data/:
web /data/web:
html /data/web/html:
/ #
/ #
/ # ifconfig
eth0 Link encap:Ethernet HWaddr ::C0:A8::
inet addr:192.168.100.1 Bcast:192.168.100.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (0.0 B) TX bytes: (0.0 B) lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (0.0 B) TX bytes: (0.0 B) / #

[root@node101.yinzhengjie.org.cn ~]# docker run --name InfrastructureImage -it -v /data/InfrastructureImage/volumes:/data/web/html busybox    #此处启动一个基础镜像

[root@node101.yinzhengjie.org.cn ~]# docker run --name nginx --network container:InfrastructureImage --volumes-from InfrastructureImage -it busybox  #此处使用"InfrastructureImage"的容器存储卷配置信息。
/ #
/ # ifconfig
eth0 Link encap:Ethernet HWaddr ::C0:A8::
inet addr:192.168.100.1 Bcast:192.168.100.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (0.0 B) TX bytes: (0.0 B) lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU: Metric:
RX packets: errors: dropped: overruns: frame:
TX packets: errors: dropped: overruns: carrier:
collisions: txqueuelen:
RX bytes: (0.0 B) TX bytes: (0.0 B) / #
/ # ls /data/ -R
/data/:
web /data/web:
html /data/web/html:
/ #
/ #

Docker存储卷篇的更多相关文章

  1. Docker系列05—Docker 存储卷详解

    本文收录在容器技术学习系列文章总目录 1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加面成,启动容器时,docker会加载只读镜像层并在镜 ...

  2. 6、Docker存储卷

    Why Data Volumes?  来自马哥教育 Data volumes Volume types  绑定挂载卷:在宿主机和容器上各指明绑定路径才能进行绑定. docker管理卷:在容器内指定挂载 ...

  3. Docker存储卷(V18.X)

    简介 介绍 Docker的存储卷称之为volume,本质上容器上的一个或者多个目录,而这些目录绕过了联合文件系统,与宿主机中的目录或者其他容器目录进行了绑定关系,这种绑定关系可以看作Linux的mou ...

  4. Docker存储卷

    六.Docker 存储卷(volume) COW:写时复制 Bind mount volume:手动mount绑定的卷 # docker run --name centos-3 -it -v /dat ...

  5. docker 存储卷 Volumes

    一,docker容器面临的困境: 容器运行中产生的数据,是放到容器栈的最顶层,当容器停止并被删除后,这些数据就被删除了. docker采用COW(写时复制)策略,导致性能低下.比如有个mysql容器, ...

  6. Docker 学习6 Docker存储卷

    一.什么是存储卷 二.为什么要用到数据卷 三.数据卷是怎么被管理的 四.存储卷种类 五.在容器中使用存储卷 1.只声明容器路径 [root@localhost docker]# docker run ...

  7. 5.Docker存储卷

    一.概述 1.Docker底层存储机制 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层. 如果运行中的容器修改了现有的一个已经存在的文件,那 ...

  8. Docker系列03—Docker 存储卷

    一.存储卷介绍 1.1 背景 Docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层: 如果运行的容器修改了 ...

  9. docker 第五篇 存储

    镜像概述复习 Docker镜像由多个只读层叠加而成,启动容器时,Docker会加载只读镜像层并在镜像栈顶部添加一个读写层 如果运行中的容器修改了现有的一个已经存在的文件,那改文件将会从读写层下面的只读 ...

随机推荐

  1. 【python基础】easydict的安装与使用

    前言 easydict允许以属性的方式访问dict类型,且可以递归地访问,使用起来比较方便. 安装 pip install easydict 使用 参考 1. easydict; 完

  2. JobStorage.Current property value has not been initialized. You must set it before using Hangfire Client or Server API.

    JobStorage.Current property value has not been initialized. You must set it before using Hangfire Cl ...

  3. vmware 虚拟机中有时获取不到IP地址

    转载: https://blog.csdn.net/valecalida/article/details/80683518 解决方法:打开vmware,然后找到编辑 然后点击虚拟网络编辑器 此时应该先 ...

  4. WPS应用技巧

    打开云文档的文件:文件-打开-我的云文档 (选择时的文档为PDF时仅扫描PDF文件)

  5. PHP设计模式 - 状态模式

    状态模式当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类.状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况.把状态的判断逻辑转移到表示不同状态的一系列类中,可以 ...

  6. JDK8从永生代到元数据区

    永生代 永生代默认的最大内存大小是在32位JVM上为64MB, 在64位JVM上为82MB.可以通过-XX:PermSize=[size]和-XX:MaxPermSize=[size]来调整. 永生代 ...

  7. python学习-36 文件处理b模式

    文件处理b模式 1.以2进制的方式读取 f = open('test.txt','rb') #以b模式就不能指定encoding data = f.read() print(data) f.close ...

  8. CF704D Captain America 上下界网络流

    传送门 现在相当于说每一个条件都有一个染成红色的盾牌的数量限制\([l,r]\),需要满足所有限制且染成红色的盾牌数量最小/最大. 注意到一个盾牌染成红色对于一行和一列都会产生影响.如果选中一个物品对 ...

  9. N皇后问题的python实现

    数据结构中常见的问题,最近复习到了,用python做一遍. # 检测(x,y)这个位置是否合法(不会被其他皇后攻击到) def is_attack(queue, x, y): for i in ran ...

  10. MVC学习笔记(四)---使用linq多表联查(SQL)

    1.数据库原型(Students表中的ID和Scores表中的StudentID是对应的) 2.实现效果:查询出每个学生各个科目的成绩(用的是MVC学习笔记(三)—用EF向数据库中添加数据的架构) C ...