Docker 管理应用数据 - 使用 volume

原文地址

卷是持久化 Docker 容器产生和使用的数据的首选方式。绑定挂载依赖主机机器的目录结构,而卷则完全由 Docker 管理。和绑定挂载相比,卷由几个优势:

  • 卷比绑定挂载更容易备份和迁移。
  • 可以通过 Docker CLI 或 Docker API 管理卷。
  • 卷在 Linux 或 Windows 容器中都可以工作。
  • 在多个容器之间共享时,卷更安全。
  • 卷驱动程序允许你在远程主机或云端存储卷,加密卷内容或增加其他功能。
  • 一个新卷的内容可以由容器预填充。

此外,和在容器的可写层持久化数据相比,卷通常是更好的选择,因为使用卷不会增加容器的体积,并且卷的内容脱离指定容器的生命周期而存在。

types-of-mounts-volume

如果容器产生了非持久化状态数据,可以考虑使用 tmpfs 挂载避免将数据永久存储到任何位置,并且通过避免写入容器的可写层来提高容器的性能。

卷使用 rprivate 绑定传播,并且绑定传播对卷不可配置。

1. 选择 -v--mount 标志

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

知识点:初学者应该使用 --mount 语法。有经验的用户会更熟悉 -v--volume 语法,但是仍然建议使用 --mount 语法,因为调查显示它更加易用。

如果需要指定卷驱动器选项,必须使用 --mount

  • -v--volume 标志:由三个由冒号(:)分隔的字段组成。这些字段必须按照正确的顺序排列,每个字段的含义并不明显。
    • 对于命名卷,第一个字段是卷的名称,并且在给定主机上是唯一的。对于匿名卷,第一个字段被省略。
    • 第二个字段是文件或目录在容器中的挂载路径。
    • 第三个字段是可选的,并且是一个逗号分隔的选项列表,例如 ro。这些选项在下面讨论。
  • --mount 标志:由多个名值对组成,逗号分隔,每个键值由 <key> = <value> 元组组成。--mount 语法比 -v--volume 更冗长,但键的顺序并不重要,并且标志的值更易于理解。
    • 要挂载的类型 type,可以是 bind、volume 或 tmpfs。本主题主要使用 volume。
    • 要挂载的源 source,对于有名字的卷,这里是卷的名字。对于匿名卷忽略这个字段。可以指定为 srcsource
    • 要挂载的目的地 destination,将文件或目录挂载在容器中的路径作为其值。 可能被指定为 destinationdsttarget
    • 只读选项 readonly,这个选项会使得挂载到容器中的绑定挂载只读。
    • 选项 volume-opt,可以被多次指定,由包含选项名和值的名值对组成。

下面的例子在可能的地方展示了 --mount-v 语法。

1.1 --mount-v 之间的表现差异

与绑定挂载不同,卷的所有选项都可用于 --mount-v 标志。

当在服务上使用卷时,仅支持 --mount

2. 创建和管理卷

与绑定挂载不同,可以通过 docker volume 命令在任何容器范围之外创建和管理卷。

创建卷:

$ 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

3. 启动带有卷的容器

启动带有卷的容器时,如果卷不存在,Docker 会自动创建这个卷。下面的例子将卷 myvol2 挂载到容器中的 /app/

下面的 --mount-v 示例产生相同的结果。注意不能同时运行,除非在运行第一个例子之后删除 devtest 容器和 myvol2 卷。

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

通过 docker inspect devtest 来验证卷被正确的创建和挂载。查看 Mounts 部分:

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

这显示挂载的是一个卷,并显示了正确的 source 和 destination,并且是读写模式。

停止容器并删除卷:

$ docker container stop devtest

$ docker container rm devtest

$ docker volume rm myvol2

3.1 启动带有卷的服务

当启动服务并定义卷时,每个服务容器都使用其自己的本地卷。如果使用本地卷驱动程序,则任何容器都不能共享此数据,但某些卷驱动程序确实支持共享存储。 AWS 的 Docker 和 Azure 的 Docker 都使用 Cloudstor 插件支持持久存储。

下面的例子启动了一个具有 4 个副本的 Nginx 服务,每个副本都使用一个名为 myvol2 的本地卷。

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

通过 docker service ps devtest-service 来验证服务正在运行:

$ 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 service create 命令不支持 -v--volume 标志。在挂载卷到服务中的容器时,必须使用 --mount 标志。

3.2 使用容器填充卷

如果启动一个创建新卷的容器(如上所述),并且在容器的要挂载的目录中具有文件或目录(例如 /app/ above),则将该目录的内容会复制到卷中。容器然后挂载并使用该卷,而使用卷的其他容器也可以访问预先填充的内容。

为了说明这一点,本示例启动一个 Nginx 容器,并使用容器的 /usr/share/nginx/html 目录(Nginx 存储其默认 HTML 内容的地方)的内容填充新卷 nginx-vol

--mount-v 示例的结果相同:

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

在运行了这些示例中的一个之后,运行下面的命令来清除容器和卷。

$ docker container stop nginxtest

$ docker container rm nginxtest

$ docker volume rm nginx-vol

4. 使用只读卷

对于某些开发的应用程序,容器需要写入绑定挂载,以便将更改传到 Docker 主机。在其他时候,容器只需要读取数据。请记住,多个容器可以挂载相同的卷,并且可以同时对它们中的某些容器进行读写挂载,对其他容器进行只读。

这个例子修改了上面的例子,但是通过在 --mount 列出的选项中添加 ro 将目录挂载为只读卷,如果存在多个选项,用逗号分隔。

--mount-v 示例的结果相同:

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

通过 docker inspect nginxtest 来验证绑定挂载创建正确。查看 Mounts 部分:

"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

5. 使用卷驱动程序

通过 docker volume create 命令创建卷时,或启动一个包含尚未创建的卷的容器时,可以指定卷驱动程序。下面的例子使用 vieux/sshfs 卷驱动程序,第一次是创建独立卷,第二次是启动容器时创建新卷。

5.1 初始化设置

这个例子假设你有两个节点,第一个节点是 Docker 主机并且可以通过 SSH 连接到第二个。

在 Docker 主机上,安装 vieux/sshfs 插件:

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

5.2 使用卷驱动程序创建卷

这个例子指定一个 SSH 密码,但是如果两个主机被配置为共享密钥,则可以省略该密码。每个卷驱动程序可能有零个或多个可配置选项,每个可选项都使用 -o 标志指定。

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

5.3 启动会使用卷驱动程序创建卷的容器

这个例子指定一个 SSH 密码,但是如果两个主机被配置为共享密钥,则可以省略该密码。每个卷驱动程序可能有零个或多个可配置选项,每个可选项都使用 -o 标志指定。如果卷驱动程序需要你传输选项,则必须使用 --mount 标志来挂载卷,而不能使用 -v

$ docker run -d \
  --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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值