使用docker目录建立一个volume,并将该volume挂载到容器的/my_Cvol目录下node
# docker volume create my_vo # docker run -itd --rm --mount source=my_vol,target=/my_Cvol busybox:latest /bin/sh
查看该volume,其源目录实际在/var/lib/docker/volumes/my_vol/_data下git
# docker volume inspect my_vol [ { "CreatedAt": "2018-12-24T22:42:18+08:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/my_vol/_data", "Name": "my_vol", "Options": null, "Scope": "local" } ]
查看使用docker inspect容器相关信息,能够看到volume的挂载信息,挂载到容器中的目录是可读写的。这样在容器的/my_Cvol目录下的操做也会同步到host的/var/lib/docker/volumes/my_vol/_data目录中。github
"Mounts": [ { "Type": "volume", "Name": "my_vol", "Source": "/var/lib/docker/volumes/my_vol/_data", "Destination": "/my_Cvol", "Driver": "local", "Mode": "z", "RW": true, "Propagation": "" }
查看host上/var/lib/docker/volumes/my_vol/_data的MAC属性能够看到它们变为了容器的MAC属性,这样也防止了容器操做不属于其权限范围的文件docker
# ls -Z -rw-------. root root system_u:object_r:container_var_lib_t:s0 metadata.db drwxr-xr-x. root root system_u:object_r:container_var_lib_t:s0 my_vol
使用tmpfs主要用于存储临时数据,因为tmpfs使用的是共享内存方式,因此其效率比较高。使用tmpfs时有以下2个选项用于指定tmpfs的大小和访问权限:centos
tmpfs-size:指定tmpfs的大小安全
tmpfs-mode:指定mount的目录权限bash
首先安装docker插件app
# docker plugin install --grant-all-permissions vieux/sshfs
在node1节点上建立位于node2节点的卷,登录的ssh密码为root,对端ip为192.168.80.161ssh
# docker volume create --driver vieux/sshfs -o sshcmd=root@192.168.80.161:/home/sshvolume -o password=root sshvolume
在host上查看容器进程的挂载信息,能够看到其实际使用了fuse.sshfs的方式挂载了来自的root@192.168.80.161:/home/sshvolume目录性能
# cat /proc/19574/mountinfo |grep 176 502 399 0:49 / /sshvolume rw,nosuid,nodev,relatime master:176 - fuse.sshfs root@192.168.80.161:/home/sshvolume rw,user_id=0,group_id=0
node1上查看docker卷信息,能够看到新增了drive为vieux/sshfs:latest,名字为sshvolume的卷
# docker volume ls DRIVER VOLUME NAME vieux/sshfs:latest sshvolume
在node1上建立一个容器,并将上一步的卷挂载到容器,在容器内部建立2个文件夹,登录到node2的/home/sshvolume,能够看到该目录下有node1的容器建立的文件夹
docker run -itd --mount source=sshvolume,target=/sshvolume busybox:latest /bin/sh
docker storage driver
storage driver负责不一样layer之间的交互,它容许在容器的读写层建立数据,读写层数据不会被持久化,且读写效率较低。如下图所示,容器镜像的layer是只读的,当建立一个容器时,会新增一个读写层,称为”container layer“,对容器的全部修改都在该layer上进行。当容器删除后,该读写层也会被删除。不一样的storage driver实现不一样,但全部的storage driver都使用了以下栈式镜像结构以及CoW(copy-on-write)策略。这是对CoW的描述
而CoW技术可让全部的容器共享image的文件系统,全部数据都从image中读取,只有当要对文件进行写操做时,才从image里把要写的文件复制到本身的文件系统进行修改。因此不管有多少个容器共享同一个image,所作的写操做都是对从image中复制到本身的文件系统中的复本上进行,并不会修改image的源文件,且多个容器操做同一个文件,会在每一个容器的文件系统里生成一个复本,每一个容器修改的都是本身的复本,相互隔离,相互不影响。使用CoW能够有效的提升磁盘的利用率。
使用docker ps -s能够查看镜像大小,能够看到"SIZE"有2个值,如container id为5b22377a773d的容器中,38B表示容器读写层的数据总和;virtual表示只读的镜像层加上读写层的大小,不一样的容器可能会共用部分或所有的镜像层,所以计算容器占用空间大小不能简单地对virtual进行叠加
# docker ps -s CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 5b22377a773d echo:v1 "/bin/sh" 2 hours ago Up 2 hours practical_darwin 38B (virtual 1.2MB) 803ee1eb5acf echo:v1 "sh -c /home/echo.sh" 2 hours ago Up 2 hours hungry_hertz 66B (virtual 1.2MB)
当在5b22377a773d中手动建立一个非空文件以后,能够看到size变为了95B
# docker ps -s CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 5b22377a773d echo:v1 "/bin/sh" 2 hours ago Up 2 hours practical_darwin 95B (virtual 1.2MB) 803ee1eb5acf 6d495122f721 "sh -c /home/echo.sh" 2 hours ago Up 2 hours hungry_hertz 66B (virtual 1.2MB)
当使用docker pull拉取一个容器镜像时,会在/var/lib/docker/<storage-driver>/layers/下面保存各个layer。
容器的读写层只保存修改过的变更,而未修改的文件或目录等则不会被保存在读写层。当修改容器中已经存在的文件时,会执行CoW操做,此时在镜像层中逐层搜索该文件,当找到该文件时,会将文件拷贝到容器的读写层(容器的镜像只读层可共享,但读写层不能够共享,CoW技术能够最大化减少容器占用的磁盘,提升磁盘利用率)。当CoW的读写效率比较低,可能会影响IO效率,须要注意如下2点:
ocker的storage driver使用插件方式提供功能。插件的选择取决于docker的版本以及使用的系统等,官方对storage driver的选择有以下建议,能够看出目前主要推荐overlay2。overlay和devicemapper已经在docker 18.09版本中被废除
Linux distribution | Recommended storage drivers | Alternative drivers |
---|---|---|
Docker Engine - Community on Ubuntu | overlay2 or aufs (for Ubuntu 14.04 running on kernel 3.13) |
overlay , devicemapper , zfs , vfs |
Docker Engine - Community on Debian | overlay2 (Debian Stretch), aufs or devicemapper (older versions) |
overlay , vfs |
Docker Engine - Community on CentOS | overlay2 |
overlay , devicemapper , zfs , vfs |
Docker Engine - Community on Fedora | overlay2 |
overlay , devicemapper , zfs , vfs |
不一样storage driver所须要的文件系统以下:
Storage driver | Supported backing filesystems |
---|---|
overlay2 , overlay |
xfs with ftype=1, ext4 |
aufs |
xfs , ext4 |
devicemapper |
direct-lvm |
btrfs |
btrfs |
zfs |
zfs |
vfs |
any filesystem |
不一样的storage driver各有优缺点:
在对storage driver修改时须要注意
Important: When you change the storage driver, any existing images and containers become inaccessible. This is because their layers cannot be used by the new storage driver. If you revert your changes, you can access the old images and containers again, but any that you pulled or created using the new driver are then inaccessible.
下面讲解下overlay2的文件结构和特色,首先下载一个centos镜像,查看改镜像有以下3个layer
# docker history centos:latest IMAGE CREATED CREATED BY SIZE COMMENT 1e1148e4cc2c 2 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 2 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 2 months ago /bin/sh -c #(nop) ADD file:6f877549795f4798a… 202MB
使用docker inspect查看该镜像能够看到其文件系统
"GraphDriver": { "Data": { "MergedDir": "/var/lib/docker/overlay2/0bb8525e901534d5c3884a9e47b91d27f887278d0433506126c45081a2a482b8/merged", "UpperDir": "/var/lib/docker/overlay2/0bb8525e901534d5c3884a9e47b91d27f887278d0433506126c45081a2a482b8/diff", "WorkDir": "/var/lib/docker/overlay2/0bb8525e901534d5c3884a9e47b91d27f887278d0433506126c45081a2a482b8/work" }, "Name": "overlay2" },
使用docker run -itd centos:latest /bin/sh启动一个centos的容器,此时会自动建立overlay须要的lowerdir,upperdir,merged和workdir,使用docker inspect命令,能够看到该容器的overlay2使用状况
"GraphDriver": { "Data": { "LowerDir": "/var/lib/docker/overlay2/7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d-init/diff:/var/lib/docker/overlay2/0bb8525e901534d5c3884a9e47b91d27f887278d0433506126c45081a2a482b8/diff", "MergedDir": "/var/lib/docker/overlay2/7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d/merged", "UpperDir": "/var/lib/docker/overlay2/7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d/diff", "WorkDir": "/var/lib/docker/overlay2/7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d/work" }, "Name": "overlay2" },
merged,upperdir和lowerdir的定义以下,upperdir为容器的读写层,lowerdir为容器的镜像只读层,merged为两者的合集
在容器建立后在/var/lib/docker/overlay2下面会生成2个新的目录,其中7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d-init用于设置容器的初始环境
drwx------. 5 root root 69 Feb 13 22:17 7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d drwx------. 4 root root 55 Feb 13 22:17 7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d-init
在7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d目录下能够看到以下文件和目录:diff为该容器的UpperDir,对于容器的读写层,在容器中建立的文件或目录都会体如今该目录中(以下图,在容器的/home下建立一个名为newfile的文件和一个名为newfoler的目录,在diff/home下面也会同步体现该变化)。
# tree -L 1
.
├── diff
├── link
├── lower
├── merged
└── work
# pwd
/var/lib/docker/overlay2/7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d/diff/home
# ll
total 0
-rw-r--r--. 1 root root 0 Feb 13 23:52 newfile
drwxr-xr-x. 2 root root 6 Feb 13 23:54 newfolder
# cat link
SKDGVP5O54VJTAXE7CQNUMIVLQ
link中包含了一个指向本目录diff文件夹的索引SKDGVP5O54VJTAXE7CQNUMIVLQ,能够在/var/lib/docker/l目录下找到其定义,实际上是个系统连接(l目录存在的意义是防止挂载时符号超出页大小限制--默认4k)。
# ll ../l |grep SKDGVP5O54VJTAXE7CQNUMIVLQ lrwxrwxrwx. 1 root root 72 Feb 13 22:17 SKDGVP5O54VJTAXE7CQNUMIVLQ -> ../7aa485418eedcd1443f76018b94b76870de074d732f6e0d5b3e4305a6d896f0d/diff
lower的内容以下,其实就是上述的GraphDriver.Data.LowerDir,对应容器镜像的只读层
# cat lower l/G6URSFRXVFKZI5ESH2BGXG7LFS:l/T6OXBIDQ2GU523P5CXINFO3VH5
merged为lower和link的合集,work为OverlayFS内部使用的文件夹。
overlayFS读文件时使用时有以下特性:
overlayFS写文件或目录时有以下特性:
因为overlayFS的CoW特性,在容器中须要注意如下2点(详情参见Use the OverlayFS storage driver):
TIPS:
参考:
https://docs.docker.com/storage/storagedriver/
https://arkingc.github.io/2017/05/05/2017-05-05-docker-filesystem-overlay/
https://docs.docker.com/storage/storagedriver/overlayfs-driver/