跟陈sir一起玩转docker卷 一

docker volume 详解

卷是持久化由Docker容器生成和使用的数据的首选机制。虽然绑定挂载依赖于主机的目录结构,但卷完全由Docker管理。与绑定挂载相比,卷有几个优点:

  • 与绑定挂载相比,卷更容易备份或迁移。
  • 您可以使用Docker CLI命令或Docker API来管理卷。
  • 卷在Linux和Windows容器上都可以工作。
  • 卷可以在多个容器之间更安全地共享。
  • 卷驱动程序允许您在远程主机或云提供程序上存储卷,加密卷的内容或添加其他功能。
  • 新卷的内容可以由容器预先填充。

另外,与使容器的可写层保存数据相比,容量通常是一个更好的选择,因为使用容量不会增加使用容器的容器的大小,而容器的内容存在于给定容器的生命周期之外。


跟陈sir一起玩转docker卷 一_第1张图片
types-of-mounts-volume.png

如果您的容器生成非持久状态数据,请考虑使用tmpfs挂载以避免将数据永久存储在任何地方,并通过避免写入容器的可写层来提高容器的性能。

卷使用rprivate绑定传播,并且绑定传播对于卷来说是不可配置的。

选择 -v or –mount 标志

最初,-v或--volume标志用于独立容器,而--mount标志用于群集服务。但是,从Docker 17.06开始,您也可以使用--mount独立的容器。一般来说,--mount更明确和详细。最大的区别在于-v语法将所有选项组合在一个字段中,而--mount语法将它们分开。以下是每个标志的语法比较。

提示:新用户应该使用--mount语法。有经验的用户可能更熟悉-v或--volume语法,但是鼓励使用--mount,因为研究表明它更易于使用。

如果您需要指定卷驱动程序选项,则必须使用--mount。

  • - v或- volume:由三个字段组成,由冒号分隔(:)。字段必须按照正确的顺序书写,并且每个字段的含义都不是立刻确定。

    • 在命名卷的情况下,第一个字段是卷的名称,在给定的主机上是惟一的。对于匿名卷,省略了第一个字段。
    • 第二个字段是在容器中安装文件或目录的路径。
    • 第三个字段是可选的,并且是一个逗号分隔的选项列表,如ro。下面讨论这些选项。
  • --mount:由多个键-值对组成,由逗号分隔,每一对由< key>= tuple(元组)组成。--mount 语法比- v或—volume 更详细,其中键对的顺序并不重要,而且标记的值更容易理解。

    • 挂载的类型(type),可以是绑定(bind)、卷(volume)或tmpfs。本主题讨论卷,因此类型将始终是卷。
    • 挂载源(source)。对于命名卷,是卷的名称。对于匿名卷,该字段被省略。可以指定为source 或src。
    • 挂在目标(destination)的值是将文件或目录安装在容器中的路径。可以指定为destination、dst或target。
    • 如果存在readonly选项,则将绑定挂载安装到容器中作为只读。
    • 可以使用键值对多次指定的volume-opt选项.

- v和- mount行为之间的差异

与绑定挂载相反,所有的卷的选项对于 --mount 和 -v 标志 都可以使用。
当卷(volume)作为服务时,只支持--mount。

创建和管理卷

与绑定挂载(bind mount)不同,您可以在任何容器范围之外创建和管理卷。
创建卷

$ docker volume create my-vol

查看卷

$ docker volume ls

local               my-vol

卷详情

$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

删除卷

$ docker volume rm my-vol

容器中使用创建的卷

如果您启动一个带了不存在的卷的容器,Docker将为您创建卷。下面的示例将卷myvol2装入容器 /app 中。

--mount

$ docker run -d \
  -it \
  --name devtest \
  --mount source=myvol2,target=/app \
  nginx:latest

-v

$ docker run -d \
  -it \
  --name devtest \
  -v myvol2:/app \
  nginx:latest

使用docker inspect devtest来验证卷的创建和挂载是否正确。查找 mount 部分:

"Mounts": [
    {
        "Type": "volume",
        "Name": "myvol2",
        "Source": "/var/lib/docker/volumes/myvol2/_data",
        "Destination": "/app",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
],

这表明挂载是一个卷,它显示了正确的源和目的地,并且挂载是读写的。
停止容器并删除卷。

$ docker container stop devtest

$ docker container rm devtest

$ docker volume rm myvol2

服务中使用卷

当您启动一个服务并定义一个卷时,每个服务容器将使用它自己的本地卷。如果您使用本地卷驱动程序,则没有一个容器可以共享这些数据,但是一些卷驱动程序确实支持共享存储。AWS的Docker和Azure的Docker都支持使用Cloudstor插件的持久性存储。
下面的示例启动一个带有四个副本的nginx服务,每个副本使用一个名为myvol2的本地卷。

$ docker service create -d \
  --replicas=4 \
  --name devtest-service \
  --mount source=myvol2,target=/app \
  nginx:lates

使用docker service ps devtest来验证服务是否正在运行:

$ docker service ps devtest-service

ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
4d7oz1j85wwn        devtest-service.1   nginx:latest        moby                Running             Running 14 seconds ago   

删除服务,停止该服务所有任务:

$ docker service rm devtest-service

服务的语法差异

docker服务创建命令不支持 - v或 --volume 语法。当将卷安装到服务的容器时,必须使用 --mount 语法

将容器原本的内容放到卷中

如果您启动一个容器,该容器创建一个新卷,如上所述,容器中包含的文件与目录正好与要挂载的卷中的目录一致(例如上面例子中的/app /),容器中的目录中的内容将被复制到卷中。然后容器将装入并使用卷,而使用此卷的其他容器也可以访问这些被copy的内容。

为了说明这一点,这个示例启动一个nginx容器,并将新卷nginx - vol填充到容器/ usr/share/nginx/html目录的内容中,这是nginx存储其默认HTML内容的地方。

The --mount and -v examples have the same end result.

$ docker run -d \
  -it \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html \
  nginx:latest
$ docker run -d \
  -it \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html \
  nginx:latest

在运行这些示例之后,运行以下命令来清理容器和卷。

$ docker container stop nginxtest

$ docker container rm nginxtest

$ docker volume rm nginx-vol

只读卷

对于一些开发中的应用,将数据写入卷中,并体现到宿主机上是非常有用的。另一方面,对于另一些应用,只允许读取卷中的内容则更加合适。毕竟一个卷可以被多个容器挂在,其中一些是读写方式,另一些是只读方式。
例子,注意mount option 使用逗号隔开

$ docker run -d \
  -it \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \
  nginx:latest
$ docker run -d \
  -it \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html:ro \
  nginx:latest

查看挂载是否正确

docker inspect nginxtest

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

删除容器和卷

$ docker container stop nginxtest

$ docker container rm nginxtest

$ docker volume rm nginx-vol

使用volume driver

当您使用 docker volume create 创建卷,或者当您创建一个容器,并与一个尚未创建的卷关联时,您可以使用volume driver

Initial set-up

这个例子假设您有两个节点,第一个节点是Docker主机,可以使用SSH连接到第二个节点。
在Docker主机上安装vieux/sshfs插件:

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

创建带volume driver 的卷

示例指定了SSH密码,但如果两个主机配置了免密码登陆(公钥免密),则可以忽略密码。每个卷驱动程序可能有零个或多个可配置选项,每个选项都使用- o标志指定。

$ docker volume create --driver vieux/sshfs \
  -o sshcmd=test@node2:/home/test \
  -o password=testpassword \
  sshvolume

创建容器时使用volume driver

如果卷驱动程序要求您传递选项,您必须使用- mount标志来挂载该卷,而不是- v。

$ docker run -d \
  -it \
  --name sshfs-container \
  --volume-driver vieux/sshfs \
  --mount src=sshvolume,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
  nginx:latest

你可能感兴趣的:(跟陈sir一起玩转docker卷 一)