Docker 持久化存储 Volumes
- 简介
- 如何选择 -v 和 --mount
- -v或--volume
- --mount
 
- 创建和管理卷
- 启动带有卷的容器
- 使用Docker Compose的卷
- 使用卷启动服务
- 使用只读卷
- 备份、恢复或迁移数据卷
- 备份卷
 
- 删除卷
- 自动删除匿名卷
- 删除所有未使用卷
 
简介
官方文档: https://docs.docker.com/storage/volumes/
卷是持久化Docker容器生成和使用的数据的首选机制。虽然绑定挂载依赖于主机的目录结构和操作系统,但卷完全由Docker管理。与绑定挂载相比,卷具有以下几个优势:
- 卷比绑定挂载更容易备份或迁移。
- 可以使用Docker CLI命令或Docker API管理卷。
- 卷可以在Linux和Windows容器上工作。
- 可以在多个容器之间更安全地共享卷。
- 卷驱动程序允许将卷存储在远程主机或云提供商上,以加密卷的内容或添加其他功能。
- 新卷的内容可以由容器预先填充。

如何选择 -v 和 --mount
一般来说,
--mount更加明确和详细。最大的区别是-v语法将所有选项组合在一个字段中,而--mount语法将它们分开。
- 如果需要指定卷驱动程序选项,则必须使用 --mount。
- 创建服务时,使用 --mount。
-v或–volume
由三个字段组成,用冒号(:)分隔。字段必须按正确的顺序排列,并且每个字段的含义不同。
docker run -d --name vtest  -v myvol2:/app:ro nginx:latest
#								[1]    [2] [3]
- [1]: 对于命名卷,第一个字段是卷的名称,并且在给定的主机上是唯一的。对于匿名卷,第一个字段被省略,由docker 生成。
- [2]: 第二个字段是容器中要挂载的目录或文件路径。
- [3]: 第三个字段是可选的,是一个逗号分隔的选项列表,如ro。
–mount
由多个键值对组成,用逗号分隔,每个键值对由一个<key>=<value>元组组成。--mount语法比-v或--volume更详细,但键的顺序并不重要。
- type键:值可以为- bind- volume- tmpfs。
- source键: 值为挂载的来源,对于命名卷,是卷的名称。对于匿名卷,此字段被省略。也可以写成为- src。
- destination键: 值为要挂载到容器中的目录或文件的路径,也可以写成- dst或者- target。
- readonly选项如果存在,会以只读方式挂载到容器。也可以写成- ro。- docker run -d \ --name=nginxtest \ --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \ nginx:latest
- volume-opt可以指定多次,选项名称和其值组成的键值对。- 从外部CSV解析器中转义值 
 如果卷驱动程序接受以逗号分隔的列表作为选项,则必须从外部CSV解析器中转义该值。要转义- volume-opt,用双引号(“)将- volume-opt括起来,并用单引号(')将整个mount参数括起来。
 例如,本地驱动程序接受挂载选项作为o参数中逗号分隔的列表。此示例演示了转义列表的正确方法。- docker service create \ --mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>,"volume-opt=o=addr=<nfs-address>,vers=4,soft,timeo=180,bg,tcp,rw"' --name myservice \ <IMAGE>
创建和管理卷
- 创建卷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 \ --name devtest \ --mount source=myvol2,target=/app \ nginx:latest
- -v- docker run -d \ --name devtest \ -v myvol2:/app \ nginx:latest
【注】:
--mount和-v示例产生的效果一样。
- 使用 docker inspect devtest查看docker 是否创建了卷,并正确挂载到容器中。"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
使用Docker Compose的卷
- 下面的示例展示了一个带有卷的Docker Compose服务:services: frontend: image: node:lts volumes: - myapp:/home/node/app volumes: myapp:
第一次运行
docker compose up会创建一个卷。当随后运行该命令时,Docker会重用相同的卷。
- 也可以使用docker volume create直接在Compose 外部创建一个卷,然后在docker-Compose.yml内部引用它,如下所示:services: frontend: image: node:lts volumes: - myapp:/home/node/app volumes: myapp: external: true
使用卷启动服务
启动服务并定义卷时,每个服务容器都使用自己的本地卷。如果使用本地卷驱动程序,则任何容器都无法共享此数据。但是,有些卷驱动程序确实支持共享存储。
 以下示例启动一个具有四个副本的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。
使用只读卷
设置权限
-  --mountdocker run -d \ --name=nginxtest \ --mount source=nginx-vol,destination=/usr/share/nginx/html,readonly \ nginx:latest
-  -vdocker run -d \ --name=nginxtest \ -v nginx-vol:/usr/share/nginx/html:ro \ nginx:latest有多个权限选项时,用逗号隔开。 
-  使用 docker inspect nginxtest, 查看详情,只看Mount部分就好。"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": "" } ],
备份、恢复或迁移数据卷
备份卷
-  创建一个容器 dbstoredocker run -v /dbdata --name dbstore ubuntu /bin/bash
-  备份 - 创建一个新容器并从 dbstore容器挂载卷。
- 将本地目录挂载到容器 /backup。
- 将 /dbdata的内容打包到/backup/backup.tar中。docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata当命令执行结束容器停止时, dbdata备份完成。
 
- 创建一个新容器并从 
-  从备份还原卷 
 使用刚刚创建的备份,可以将其恢复到同一个容器,或者恢复到另一个容器。- 恢复到另一个容器 dbstore2docker run -v /dbdata --name dbstore2 ubuntu /bin/bashdocker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"
 
- 恢复到另一个容器 
删除卷
自动删除匿名卷
删除容器时并不会自动删除匿名卷,运行容器时使用
--rm选项自动删除匿名卷。
docker run --rm -v /foo -v awesome:/bar busybox top
--rm可以自动删除/foo的匿名卷,但是命名卷awesome不会被删除。
如果其它容器使用
--volumes-from绑定了匿名卷,容器删除时,匿名卷会被保留,不会被删除。
删除所有未使用卷
- 删除所有未使用的卷释放空间
docker volume prune


















