docker挂载研究



Docker 中的三种挂载方式

bind

把宿主机的某个目录(或文件)挂载到指容器的指定目录(后文件)下,比如下面的命令就表示通过 Bind 方式将外部的 HTML 文档挂载到 Nginx 容器的模式网站根目录下:

docker run -v ~/zioyi/html:/usr/share/nginx/html -p 81:80 -d --name nginx_bind nginx:latest

这种方式的缺点就是被挂载的宿主机目录(或文件)不收保护,任何容器都可以去随意修改。

Volume 

Volume 模式下,我们需要通过docker volume命令来创建一个 Volume。实际上,是在 Docker 的/var/lib/docker/volumes/文件夹内创建一个相同名字的文件夹来保存数据。因为这个文件夹在 Docker 管控范围里,Docker 可以根据挂载的设定来控制容器对 Volume 的读写权限。

 创建 volume
$ docker volume create nginx-volume
nginx-volume
$ docker run --mount type=volume,source=nginx-volume,destination=/usr/share/nginx/html -p 82:80 -d --name nginx_volume nginx:latest

此时,nginx_volume 容器已经挂载了 nginx-volume 卷,通过 inpsect 命令可以看到:

shelll代码解读复制代码

docker inspect nginx_volume
{...
"Mounts": [
            {
                "Type": "volume",
                "Name": "nginx-volume",
                "Source": "/var/lib/docker/volumes/nginx-volume/_data",
                "Destination": "/usr/share/nginx/html",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],
...}

当我们删除容器 nginx_volum 时,volume 也不会删除

此外,我们还可以在挂载时设定容器只能读取卷,无法进行写操作,这种方式多用于容器读取配置文件的场景:

shell 代码解读复制代码$ docker run --mount type=volume,source=nginx-volume,destination=/usr/share/nginx/html,readonly -p 82:80 -d --name nginx_volume nginx:latest
$ docker exec -it nginx_volume bash
root@782b11b3cc43:/#
# 当我们再次修改时报错
root@782b11b3cc43:/# echo "hello" > /usr/share/nginx/html/index.html
bash: /usr/share/nginx/html/index.html: Read-only file system

tmpfs 

tmpfs 挂载是临时的,仅保留在主机内存中。当容器停止时,tmpfs 挂载被移除,写入的文件不会被持久化

shell代码解读复制代码
$ docker run --mount type=tmpfs,destination=/usr/share/nginx/html -p 83:80 -d --name nginx_tmpfs nginx:latest

$ docker inspect nginx_tmpfs
{...
"Mounts": [
            {
                "Type": "tmpfs",
                "Source": "",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
...}

tmpfs 无法对容器内产生的数据持久化,一般不使用。

总结

对比 Docker 三种挂载方式:

BindVolumetmpfs
volume 位置可指定任意位置/var/lib/docker/volumes/…宿主机内存中
对已有mount point 影响隐藏并替换为 volume原有数据复制到 volume-
是否支持单个文件支持不支持,只能是目录-
权限控制可设置为只读,默认为读写权限可设置为只读,默认为读写权限-
移植性移植性弱,与 host path 绑定移植性强,无需指定 host 目录-
是否支持持久化支持支持不支持

关于 Volume Volume 模式并不是 Docker 一开始就有的,Docker 最初认为 Volume 就只是一种“外部宿主机的磁盘存储到内部容器的映射关系”,但后来发现事情并没有那么简单:存储的位置并不局限于外部宿主机,存储的介质并不局限于物理磁盘,存储的管理也并不局限于映射关系。Bind 模式无法很好地解决多跨宿主机共享存储的问题、Bind 模式的管理问题等。 提出 Volume 的最核心的目的是提升Docker对不同存储介质的支撑能力,这同时也可以减轻Docker本身的工作量。存储不仅有挂载在宿主机上的物理存储,还有网络存储,Docker 抽象出了存储启动(Sotroage Driver)来去解决对网络存储的读写问题。