网站公告

本次更新:没啥更新的

“钱塘江上潮信起,今日方知我是我”

Skip to content

数据卷 ​

字数: 0 字 时长: 0 分钟

1. 数据卷概述 ​

Docker 数据卷概述

在前面的 Nginx 案例中,我们直接进入容器内部修改 index.html 文件。虽然能够完成修改,但操作并不方便,而且数据与容器本身绑定在一起。

一旦容器被删除,容器内部产生的数据和文件变化也可能随之丢失。对于配置文件、日志、数据库数据等需要长期保存的内容,如果全部直接存放在容器内部,后续维护、备份和迁移都会比较麻烦。

容器与数据耦合

因此,实际使用 Docker 时,通常会将需要长期保存的数据从容器内部独立出来,让容器主要负责运行应用,而数据交给宿主机或 Docker 管理的存储空间保存。

这就是 Docker 数据卷(Volume)要解决的问题:

将容器与数据解耦,降低数据与容器生命周期之间的依赖,使数据持久化、管理、备份和迁移更加方便。


2. 数据卷操作 ​

Docker 提供了 docker volume 命令用于管理数据卷。

基本语法:

bash
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

Docker Volume 常用命令

2.1 创建数据卷 ​

创建一个名为 html 的数据卷:

bash
docker volume create html

创建数据卷


2.2 查看数据卷 ​

查看当前所有数据卷:

bash
docker volume ls

查看所有数据卷

可以看到刚刚创建的:

text
html

2.3 查看数据卷详细信息 ​

通过 docker volume inspect 可以查看数据卷的详细信息:

bash
docker volume inspect html

查看数据卷详细信息

例如:

text
/var/lib/docker/volumes/html/_data

就是 html 数据卷在宿主机上的实际存储位置。

常见字段说明:

字段含义人话理解示例值
CreatedAt数据卷创建时间这个 Volume 是什么时候创建的2024-05-05T21:59:23-04:00
Driver数据卷使用的存储驱动这个数据卷由谁管理,默认通常是 locallocal
Labels数据卷标签可以给 Volume 添加自定义标记null
Mountpoint数据卷在宿主机上的实际存储位置Docker 最终把数据放在哪个目录/var/lib/docker/volumes/html/_data
Name数据卷名称创建 Volume 时指定的名字html
Options数据卷额外参数是否配置了额外选项null
Scope数据卷作用范围local 表示属于当前 Docker 主机local

其中最重要的是:

Mountpoint 表示数据卷在宿主机上的实际存储位置。


2.4 删除数据卷 ​

删除所有当前未被容器使用的数据卷:

bash
docker volume prune

清理未使用的数据卷

docker volume prune 会批量删除当前未被容器使用的数据卷,执行前应确认其中没有需要保留的数据。

删除指定的数据卷:

bash
docker volume rm html

删除指定数据卷

再次查看:

bash
docker volume ls

可以看到 html 数据卷已经被删除。


3. 挂载数据卷 ​

在创建容器时,可以通过 -v 参数,将一个数据卷挂载到容器中的指定目录。

Docker 数据卷挂载

基本格式:

bash
docker run \
    --name mn \
    -v html:/usr/share/nginx/html \
    -p 8080:80 \
    -d \
    nginx

其中最关键的是:

bash
-v html:/usr/share/nginx/html

格式为:

text
-v 数据卷名称:容器内目录

可以理解为:

text
html:/usr/share/nginx/html
 │              │
 │              └── 容器内目录
 │
 └── 数据卷名称

也就是说,将名为 html 的数据卷挂载到容器中的:

text
/usr/share/nginx/html

挂载关系如下:

text
宿主机
/var/lib/docker/volumes/html/_data
              │
              ↓
         html 数据卷
              │
              ↓
Nginx 容器
/usr/share/nginx/html

挂载完成后,容器中的挂载目录与数据卷使用的是同一份数据。

因此:

  • 在容器中修改挂载目录,修改结果会保存到数据卷中
  • 数据卷中的内容发生变化,容器访问该目录时也能看到变化
  • 删除容器后,只要数据卷没有被删除,数据仍然可以继续保留

如果指定的数据卷不存在,Docker 在使用 -v 挂载时通常会自动创建,也可以提前手动创建:

bash
docker volume create html

简单来说:

-v 数据卷名称:容器目录,左边是数据卷,右边是容器中使用这份数据的目录。


3.1 Nginx 挂载数据卷 ​

需求: 创建一个 Nginx 容器,将 Nginx 的 HTML 目录挂载到数据卷中,并通过宿主机修改页面内容。

Nginx 默认的 HTML 目录为:

text
/usr/share/nginx/html

创建容器并挂载数据卷:

bash
docker run \
    --name mn \
    -p 80:80 \
    -v html:/usr/share/nginx/html \
    -d \
    nginx

Nginx 挂载数据卷

查看 html 数据卷在宿主机上的实际位置:

bash
docker volume inspect html

查看 html 数据卷挂载位置

例如:

text
/var/lib/docker/volumes/html/_data

进入数据卷目录:

bash
cd /var/lib/docker/volumes/html/_data

修改 Nginx 页面:

bash
vi index.html

此时修改的是数据卷中的文件,Nginx 容器访问 /usr/share/nginx/html 时也会读取到修改后的内容。

直接进入 /var/lib/docker/volumes/ 修改文件主要适合学习和排查。这个目录属于 Docker 管理的内部存储位置,如果实际业务需要频繁从宿主机直接操作文件,通常更适合使用 Bind Mount。


4. 挂载宿主机目录(Bind Mount) ​

除了使用 Docker 管理的数据卷,还可以直接将宿主机上的文件或目录挂载到容器中,这种方式通常称为 Bind Mount(绑定挂载)。

两种方式的关系如下:

text
Volume:

宿主机目录
    ↓
Docker Volume
    ↓
容器目录
text
Bind Mount:

宿主机目录
    ↓
容器目录

Volume 与 Bind Mount

Bind Mount 的基本格式:

text
-v 宿主机目录:容器内目录

也可以直接挂载单个文件:

text
-v 宿主机文件:容器内文件

例如:

bash
-v /tmp/mysql/data:/var/lib/mysql

表示:

text
/tmp/mysql/data
        │
        ↓
MySQL 容器
/var/lib/mysql

简单来说:

Volume 是 Docker 帮你管理数据存放的位置,Bind Mount 是自己明确指定宿主机上的文件或目录。


4.1 MySQL 挂载案例 ​

需求: 创建并运行一个 MySQL 容器,将 MySQL 的数据目录和配置文件直接挂载到宿主机。

1)拉取 MySQL 镜像 ​

bash
docker pull mysql:8.0.30

拉取 MySQL 镜像


2)创建数据目录 ​

创建宿主机目录:

bash
cd /tmp
mkdir -p mysql/data

创建 MySQL 数据目录

该目录后面会挂载到:

text
/var/lib/mysql

用于保存 MySQL 数据。


3)创建配置目录 ​

创建配置目录:

bash
mkdir -p mysql/conf

进入目录:

bash
cd mysql/conf

创建配置文件:

bash
vi hmy.cnf

写入:

ini
[mysqld]
skip-name-resolve
character_set_server=utf8
datadir=/var/lib/mysql
server-id=1000

保存退出后查看:

bash
cat hmy.cnf

创建 MySQL 配置文件


4)确定 MySQL 挂载位置 ​

MySQL 数据目录:

text
/var/lib/mysql

MySQL 数据目录

MySQL 可以通过:

text
/etc/mysql/conf.d/

加载额外配置文件。

MySQL 配置目录

因此可以将:

text
/tmp/mysql/conf/hmy.cnf

挂载为:

text
/etc/mysql/conf.d/hmy.cnf

这样不需要直接覆盖 MySQL 默认的主配置文件。


5)创建并运行 MySQL 容器 ​

执行:

bash
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 容器

这样 MySQL 的数据会直接保存到宿主机的:

text
/tmp/mysql/data

即使重新创建容器,只要继续挂载这个目录,就可以继续使用原来的数据。


5. Volume 与 Bind Mount 对比 ​

Docker 常见的数据挂载方式主要有 Volume 和 Bind Mount。

对比项VolumeBind 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 ​

text
-v volume名称:容器内目录

例如:

bash
-v html:/usr/share/nginx/html

Bind Mount ​

挂载宿主机目录:

text
-v 宿主机目录:容器内目录

例如:

bash
-v /tmp/mysql/data:/var/lib/mysql

挂载宿主机文件:

text
-v 宿主机文件:容器内文件

例如:

bash
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf

两者的核心区别:

Volume 的数据位置主要由 Docker 管理,而 Bind Mount 的宿主机路径由用户自己管理。

无论使用哪种方式,核心目的都是:

让数据脱离容器自身的生命周期,实现容器与数据的解耦。

Noctiflorous Garden · MIT License