volumes是保存Docker容器生成和使用的数据的首选机制。bind mounts依赖于主机的目录结构,而卷则完全由Docker管理。卷比bind mounts有几个优点:

  1. volumes比bind mounts跟容易备份或迁移。
  2. 可以使用Docker API进行管理。
  3. volumes可以在Linux或Windows平台的容器上工作。
  4. 可以在多个容器之间安全共享
  5. 允许将volumes存储在远程主机或是云服务提供商。

volumes的生命周期在容器之外。这是Docker官网给出的一幅图
我的理解为:

  1. 容器可以使用bind mount的方式将数据存储在主机的文件系统中。
  2. 容器可以使用volume的方式将数据存储在卷中,volume属于Docker管理,volume的存储最终还是在文件系统中。
  3. 容器可以使用tmpfs mount的方式将数据存放在内存中。

个人觉得volume就像是给bind mount模式起了个名字,并且作为一个整体被Docker管理。
具体操作一下,卷的创建方式有很多种,比如直接使用:

docker volume create my-vol

或是在容器启动时使用-v

docker run -d --name test01 -v my-vol2:/app nginx:latest

还可以使用–mount

docker run -d --name test02 --mount src=my-vol3,target=/app nginx:latest

这里简单解释一下-v、-mount的参数含义。
-v 后面可以跟三个值,分别用“:”冒号隔开,当然–volume和-v是一样的。

  1. 第一个值可选,是用来设值volume卷名的。
  2. 第二个值必填,设值容器内的挂载路径。
  3. 第三个值可选,是一些volume的属性设值,比如:ro(只读)。

-mount 后跟若干个key=val,也就是键值对,用","逗号隔开。分别有如下一些key:

  1. type : 可选值有bind、volume、tmpfs,也就是设值卷的类型。
  2. source | src : 用来设值卷名。
  3. destination : 目的地,也就是容器内的挂载路径。
  4. readonly : 设值卷的只读属性。
  5. volume-opt : 该参数可以有多个,值还是一个key=val,也就是像 volume-opt=key=val这样子。用于设置其他属性。

我们还可以使用:docker volume ls 查看列表,使用:docker inspect my-vol3 查看详情。

[
    {
        "CreatedAt": "2018-11-22T04:22:37-05:00", # 卷的创建时间
        "Driver": "local", # 卷的驱动
        "Labels": null, 
        "Mountpoint": "/var/lib/docker/volumes/my-vol3/_data", # 卷在文件系统的存储位置
        "Name": "my-vol3", # 卷名
        "Options": null, 
        "Scope": "local"
    }
]

删除volume:docker volume rm my-vol3,这里注意,删除volume之前删除使用了该volume的容器。
当然也可以在同主机中的容器之间共享volume,做个简单的示例。
启动俩个nginx容器,使用同一个volume,volume在容器中的挂载位置是:/usr/share/nginx/html 这个位置是Nginx默认存储HTML的文件夹。
启动第一个Nginx容器:

 docker run -d --name nginx01 -p 10080:80 -v nginx-vol:/usr/share/nginx/html nginx:latest

启动成功后我们到nginx-vol卷的目录下修改index.html内容,删除body中<h1>Welcome to nginx!</h1> 以外的全部内容,访问Nginx首页:在这里插入图片描述
再启动第二个容器:

docker run -d --name nginx02 -p 10081:80 -v nginx-vol:/usr/share/nginx/html nginx:latest

访问首页:
在这里插入图片描述
没有修改第二个容器,它使用了我在第一个容器中修改后的首页。
同主机下的容器共享volume实现还是比较简单,接下来搞一下不同主机下的容器共享volume。
这里需要改变volume driver了,不能使用之前的local。
官方文档中的例子使用的是vieux/sshfs,这里先安装一下插件

docker plugin install --grant-all-permissions vieux/sshfs

这里我们启动俩个机器,ip分别是:

  • 192.168.1.164
  • 192.168.1.130

前面的内容都是在192.168.1.164这台主机上操作的,这里我继续使用之前创建的nginx01容器,启动容器并查看一下容器的Mounts:
在这里插入图片描述
Source是nginx-vol卷在文件系统中的存储位置,待会会用到。

切换到192.168.1.130主机,之前的插件只需要安装在这台主机上,同样运行一个nginx容器,但这里要使用vieux/sshfs驱动创建卷:

docker run -d --name nginx-sshvol \
-p 10080:80 \
--mount src=sshvol,target=/usr/share/nginx/html,type=volume,volume-driver=vieux/sshfs,volume-opt=sshcmd=root@192.168.1.164:/var/lib/docker/volumes/nginx-vol/_data,volume-opt=password=**** \
nginx:latest

启动成功后访问192.168.1.130:10080,不出意外的话应该和之前一样,页面只有一个欢迎标题。可实际显示的是403,Bug可能会迟到,但永远不会缺席。
查看容器启动日志:

[root@localhost ~]# docker logs nginx-sshvol 
192.168.1.157 - - [23/Nov/2018:02:29:17 +0000] "GET / HTTP/1.1" 403 571 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" "-"
2018/11/23 02:29:17 [error] 6#6: *1 "/usr/share/nginx/html/index.html" is forbidden (13: Permission denied), client: 192.168.1.157, server: localhost, request: "GET / HTTP/1.1", host: "192.168.1.130:10080"
2018/11/23 02:29:17 [error] 6#6: *1 open() "/usr/share/nginx/html/favicon.ico" failed (13: Permission denied), client: 192.168.1.157, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "192.168.1.130:10080", referrer: "http://192.168.1.130:10080/"
192.168.1.157 - - [23/Nov/2018:02:29:17 +0000] "GET /favicon.ico HTTP/1.1" 403 571 "http://192.168.1.130:10080/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" "-"

这是一个很常见的Nginx权限不足问题,我们将nginx.conf配置中的user改为root即可。由于容器中没有vi命令,我们用docker cp 命令将nginx.conf复制到宿主机中,修改后同样使用docker cp再给它覆盖回去。

复制配置到宿主机:docker cp nginx-sshvol:/etc/nginx/nginx.conf ./nginx.conf
覆盖容器中的配置:docker cp ./nginx.conf nginx-sshvol:/etc/nginx/nginx.conf

覆盖配置之后重启容器,再次访问,成功解决:
在这里插入图片描述

Logo

更多推荐