数据卷
字数: 0 字 时长: 0 分钟
1. 数据卷概述

在前面的 Nginx 案例中,我们直接进入容器内部修改 index.html 文件。虽然能够完成修改,但操作并不方便,而且数据与容器本身绑定在一起。
一旦容器被删除,容器内部产生的数据和文件变化也可能随之丢失。对于配置文件、日志、数据库数据等需要长期保存的内容,如果全部直接存放在容器内部,后续维护、备份和迁移都会比较麻烦。

因此,实际使用 Docker 时,通常会将需要长期保存的数据从容器内部独立出来,让容器主要负责运行应用,而数据交给宿主机或 Docker 管理的存储空间保存。
这就是 Docker 数据卷(Volume)要解决的问题:
将容器与数据解耦,降低数据与容器生命周期之间的依赖,使数据持久化、管理、备份和迁移更加方便。
2. 数据卷操作
Docker 提供了 docker volume 命令用于管理数据卷。
基本语法:
docker volume [COMMAND]常见命令如下:
| 命令 | 作用 | 人话理解 | 示例 |
|---|---|---|---|
docker volume create | 创建一个 Volume | 新建一个数据卷 | docker volume create html |
docker volume inspect | 查看一个或多个 Volume 的详细信息 | 看数据卷保存在哪里、有哪些配置 | docker volume inspect html |
docker volume ls | 列出所有 Volume | 看当前有哪些数据卷 | docker volume ls |
docker volume prune | 删除所有未被使用的 Volume | 批量清理没有被容器使用的数据卷 | docker volume prune |
docker volume rm | 删除一个或多个指定的 Volume | 删除指定数据卷 | docker volume rm html |

2.1 创建数据卷
创建一个名为 html 的数据卷:
docker volume create html
2.2 查看数据卷
查看当前所有数据卷:
docker volume ls
可以看到刚刚创建的:
html2.3 查看数据卷详细信息
通过 docker volume inspect 可以查看数据卷的详细信息:
docker volume inspect html
例如:
/var/lib/docker/volumes/html/_data就是 html 数据卷在宿主机上的实际存储位置。
常见字段说明:
| 字段 | 含义 | 人话理解 | 示例值 |
|---|---|---|---|
CreatedAt | 数据卷创建时间 | 这个 Volume 是什么时候创建的 | 2024-05-05T21:59:23-04:00 |
Driver | 数据卷使用的存储驱动 | 这个数据卷由谁管理,默认通常是 local | local |
Labels | 数据卷标签 | 可以给 Volume 添加自定义标记 | null |
Mountpoint | 数据卷在宿主机上的实际存储位置 | Docker 最终把数据放在哪个目录 | /var/lib/docker/volumes/html/_data |
Name | 数据卷名称 | 创建 Volume 时指定的名字 | html |
Options | 数据卷额外参数 | 是否配置了额外选项 | null |
Scope | 数据卷作用范围 | local 表示属于当前 Docker 主机 | local |
其中最重要的是:
Mountpoint表示数据卷在宿主机上的实际存储位置。
2.4 删除数据卷
删除所有当前未被容器使用的数据卷:
docker volume prune
docker volume prune会批量删除当前未被容器使用的数据卷,执行前应确认其中没有需要保留的数据。
删除指定的数据卷:
docker volume rm html
再次查看:
docker volume ls可以看到 html 数据卷已经被删除。
3. 挂载数据卷
在创建容器时,可以通过 -v 参数,将一个数据卷挂载到容器中的指定目录。

基本格式:
docker run \
--name mn \
-v html:/usr/share/nginx/html \
-p 8080:80 \
-d \
nginx其中最关键的是:
-v html:/usr/share/nginx/html格式为:
-v 数据卷名称:容器内目录可以理解为:
html:/usr/share/nginx/html
│ │
│ └── 容器内目录
│
└── 数据卷名称也就是说,将名为 html 的数据卷挂载到容器中的:
/usr/share/nginx/html挂载关系如下:
宿主机
/var/lib/docker/volumes/html/_data
│
↓
html 数据卷
│
↓
Nginx 容器
/usr/share/nginx/html挂载完成后,容器中的挂载目录与数据卷使用的是同一份数据。
因此:
- 在容器中修改挂载目录,修改结果会保存到数据卷中
- 数据卷中的内容发生变化,容器访问该目录时也能看到变化
- 删除容器后,只要数据卷没有被删除,数据仍然可以继续保留
如果指定的数据卷不存在,Docker 在使用 -v 挂载时通常会自动创建,也可以提前手动创建:
docker volume create html简单来说:
-v 数据卷名称:容器目录,左边是数据卷,右边是容器中使用这份数据的目录。
3.1 Nginx 挂载数据卷
需求: 创建一个 Nginx 容器,将 Nginx 的 HTML 目录挂载到数据卷中,并通过宿主机修改页面内容。
Nginx 默认的 HTML 目录为:
/usr/share/nginx/html创建容器并挂载数据卷:
docker run \
--name mn \
-p 80:80 \
-v html:/usr/share/nginx/html \
-d \
nginx
查看 html 数据卷在宿主机上的实际位置:
docker volume inspect html
例如:
/var/lib/docker/volumes/html/_data进入数据卷目录:
cd /var/lib/docker/volumes/html/_data修改 Nginx 页面:
vi index.html此时修改的是数据卷中的文件,Nginx 容器访问 /usr/share/nginx/html 时也会读取到修改后的内容。
直接进入
/var/lib/docker/volumes/修改文件主要适合学习和排查。这个目录属于 Docker 管理的内部存储位置,如果实际业务需要频繁从宿主机直接操作文件,通常更适合使用 Bind Mount。
4. 挂载宿主机目录(Bind Mount)
除了使用 Docker 管理的数据卷,还可以直接将宿主机上的文件或目录挂载到容器中,这种方式通常称为 Bind Mount(绑定挂载)。
两种方式的关系如下:
Volume:
宿主机目录
↓
Docker Volume
↓
容器目录Bind Mount:
宿主机目录
↓
容器目录
Bind Mount 的基本格式:
-v 宿主机目录:容器内目录也可以直接挂载单个文件:
-v 宿主机文件:容器内文件例如:
-v /tmp/mysql/data:/var/lib/mysql表示:
/tmp/mysql/data
│
↓
MySQL 容器
/var/lib/mysql简单来说:
Volume 是 Docker 帮你管理数据存放的位置,Bind Mount 是自己明确指定宿主机上的文件或目录。
4.1 MySQL 挂载案例
需求: 创建并运行一个 MySQL 容器,将 MySQL 的数据目录和配置文件直接挂载到宿主机。
1)拉取 MySQL 镜像
docker pull mysql:8.0.30
2)创建数据目录
创建宿主机目录:
cd /tmp
mkdir -p mysql/data
该目录后面会挂载到:
/var/lib/mysql用于保存 MySQL 数据。
3)创建配置目录
创建配置目录:
mkdir -p mysql/conf进入目录:
cd mysql/conf创建配置文件:
vi hmy.cnf写入:
[mysqld]
skip-name-resolve
character_set_server=utf8
datadir=/var/lib/mysql
server-id=1000保存退出后查看:
cat hmy.cnf
4)确定 MySQL 挂载位置
MySQL 数据目录:
/var/lib/mysql
MySQL 可以通过:
/etc/mysql/conf.d/加载额外配置文件。

因此可以将:
/tmp/mysql/conf/hmy.cnf挂载为:
/etc/mysql/conf.d/hmy.cnf这样不需要直接覆盖 MySQL 默认的主配置文件。
5)创建并运行 MySQL 容器
执行:
docker run \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3306:3306 \
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
-v /tmp/mysql/data:/var/lib/mysql \
-d \
mysql:8.0.30其中:
| 参数 | 作用 |
|---|---|
--name mysql | 容器名称 |
-e MYSQL_ROOT_PASSWORD=123456 | 设置 MySQL Root 密码 |
-p 3306:3306 | 映射 MySQL 端口 |
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf | 挂载 MySQL 配置文件 |
-v /tmp/mysql/data:/var/lib/mysql | 挂载 MySQL 数据目录 |
-d | 后台运行 |
mysql:8.0.30 | 使用的镜像 |
执行结果:

这样 MySQL 的数据会直接保存到宿主机的:
/tmp/mysql/data即使重新创建容器,只要继续挂载这个目录,就可以继续使用原来的数据。
5. Volume 与 Bind Mount 对比
Docker 常见的数据挂载方式主要有 Volume 和 Bind Mount。
| 对比项 | Volume | Bind Mount |
|---|---|---|
| 写法 | -v volume名称:容器目录 | -v 宿主机目录:容器目录 |
| 存储位置 | 由 Docker 管理 | 用户自己指定 |
| 示例 | -v html:/usr/share/nginx/html | -v /tmp/mysql/data:/var/lib/mysql |
| 管理方式 | 使用 docker volume 管理 | 直接管理宿主机文件 |
| 与宿主机目录耦合 | 较低 | 较高 |
| 可移植性 | 较好 | 依赖宿主机目录结构 |
| 常见场景 | 数据持久化、Docker 管理的数据 | 配置文件、开发文件、明确指定的数据目录 |
简单来说:
Volume:Docker 帮你管理数据放在哪里。
Bind Mount:自己指定宿主机上的哪个文件或目录给容器使用。
6. 小结
Docker 可以通过 -v 参数将数据挂载到容器中。
Volume
-v volume名称:容器内目录例如:
-v html:/usr/share/nginx/htmlBind Mount
挂载宿主机目录:
-v 宿主机目录:容器内目录例如:
-v /tmp/mysql/data:/var/lib/mysql挂载宿主机文件:
-v 宿主机文件:容器内文件例如:
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf两者的核心区别:
Volume 的数据位置主要由 Docker 管理,而 Bind Mount 的宿主机路径由用户自己管理。
无论使用哪种方式,核心目的都是:
让数据脱离容器自身的生命周期,实现容器与数据的解耦。