一、简介

Volumes 是由容器引擎实现的持久化数据存储。Compose 提供了一种中立的方式让服务挂载卷,并通过配置参数将它们分配给基础设施。顶级的 volumes 声明允许您配置可在多个服务之间重用的命名卷。

要在多个服务之间使用一个卷,必须在 services 顶级元素中通过 volumes 属性显式地为每个服务授予访问权限。volumes 属性具有额外的语法,可提供更细粒度的控制。

二、示例

1
2
3
4
5
6
7
8
9
10
11
12
13
services:
backend:
image: example/database
volumes:
- db-data:/etc/data

backup:
image: backup-service
volumes:
- db-data:/var/lib/backup/data

volumes:
db-data:

上面的示例中,包含两个服务。其中数据库的数据目录通过命名为 db-data 的卷与另一个服务共享,以便定期备份。

db-data 卷分别挂载在 /var/lib/backup/data/etc/data 容器路径上,分别用于 backend 服务和 backup 服务。

在执行 docker compose up 时如果卷不存在则会创建。如果存在将使用现有卷。如果在 Compose 之外手动删除了卷,将会重新创建。

注意:上面的卷名为 db-data,会创建名称后缀为 db-data 的卷,卷名称前缀为顶级元素 name 中声明的值或者说是 ${COMPOSE_PROJECT_NAME} 变量的值,例如 name: postgres-demo,最终创建的卷名称为 postgres-demo_db-data

三、属性

顶级 volumes 元素下的属性可以为空,在这种情况下,它使用容器引擎的默认配置来创建卷。

1、driver

该属性指定使用哪个卷驱动程序。如果驱动程序不可用,Compose 将报错并不部署应用程序。

示例:

1
2
3
volumes:
db-data:
driver: vieux/sshfs

2、driver_ops

该属性指定了一个键值对列表来传递给卷驱动。

1
2
3
4
5
6
volumes:
example:
driver_opts:
type: "nfs"
o: "addr=10.40.0.199,nolock,soft,rw"
device: ":/docker/example"

3、name

该属性为卷自定义名称。这个名称可以用来在 Compose 文件或其他地方引用该卷,特别是在卷名包含特殊字符时,直接通过名称引用可以避免潜在的解析问题。当你为卷指定一个 name 时,这个名称将直接用于卷的标识,并且它不会被自动地添加任何与栈(stack)名称相关的前缀或后缀(顶级元素 name 前缀等)。

1
2
3
volumes:
db-data:
name: "my-app-data"

上面所说的,卷名中包含特殊字符,示例如下:

1
2
3
volumes:
db-data:
name: "my-postgres-db-data!!!@@@###"

如果你没有为卷显式地指定 name 属性,Docker Compose 将自动生成一个基于 Compose 文件所在目录名称、服务名称和卷声明的拼接的默认名称。这个自动生成的名称不会包含任何特殊字符,并且它会在 Docker 宿主机上唯一标识该卷。

卷的名称可以设置为一个参数化选项,这意味着你可以在 Compose 文件中的卷的名称中使用插值,但实际的卷的名称在部署时动态设置的。这种做法提供了灵活性和可重用性,尤其是在需要跨多个环境(如开发、测试和生产)部署应用时。

例如,如果在 .env 文件中有环境变量 DATABASE_VOLUME=my_volume_001

1
2
3
volumes:
db-data:
name: ${DATABASE_VOLUME}

运行 docker compose up 时,会使用名为 my_volume_001 的卷。

也可以与 external 属性结合使用。这意味着用于在平台上查找实际卷的名称与用于在 Compose 文件中引用卷的名称是分开设置的:

1
2
3
4
volumes:
db-data:
external: true
name: actual-name-of-volume

4、external

如果设置为 true:

  • external 属性指定此卷已经存在,卷的生命周期在应用程序的生命周期之外进行管理。如果卷不存在,则 Compose 不创建此卷并报错。
  • name 外的所有其他属性都无关紧要。如果 Compose 检测到其他任何属性,会将 Compose 文件视为无效并且拒绝执行。
1
2
3
4
5
6
7
8
9
services:
backend:
image: example/database
volumes:
- db-data:/etc/data

volumes:
db-data:
external: true

在上面的例子中,Compose 不会去创建名为 {project_name}_db-data 的卷,而是去查询名为 db-data 的卷并将其挂在到名为 backend 的容器中。

5、labels

labels 用于向卷添加元数据。该属性可以设置为数字或字典值。

建议使用反向 DNS 表示法,以防止标签与其他软件使用的标签冲突。

1
2
3
4
5
6
volumes:
db-data:
labels:
com.example.description: "Database volume"
com.example.department: "IT/Ops"
com.example.label-with-empty-value: ""
1
2
3
4
5
6
volumes:
db-data:
labels:
- "com.example.description=Database volume"
- "com.example.department=IT/Ops"
- "com.example.label-with-empty-value"

关于标签,现在已知的情报:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ docker volume ls 
todo-list-app_todo-mysql-data
$ docker volume inspect todo-list-app_todo-mysql-data
[
{
"CreatedAt": "2024-07-12T06:13:46Z",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "todo-list-app",
"com.docker.compose.version": "2.26.1",
"com.docker.compose.volume": "todo-mysql-data"
},
"Mountpoint": "/var/lib/docker/volumes/todo-list-app_todo-mysql-data/_data",
"Name": "todo-list-app_todo-mysql-data",
"Options": null,
"Scope": "local"
}
]

相关链接

Volumes | Docker Docs

Docker Engine Storage | z2huo

[[Compose 顶级元素 Services#8、volumes]]

[[Docker Engine Storage#1、Volumes]]

[[Docker Engine Storage#2、Bind mounts]]

OB tags

#Docker