每天半小时,轻松学Docker第六篇:Docker卷与绑定挂载

一、上期回顾
每天半小时,轻松学Docker第五篇:Docker 容器管理
二、什么是卷?
Docker采用了在宿主机与容器之间,或容器与容器之间进行文件/目录的映射来解决这些问题。为此,Docker引入了“卷”(volume)机制和“绑定挂载”(bind mounts)。卷由Docker管理,非Docker进程不应该修改卷文件系统中的内容,卷是在Docker中保留数据的最佳方式。Docker提供了对卷的创建、列表、详情、删除命令。
绑定挂载优点是具有较好的性能,缺点是它们依赖于具有特定目录结构的宿主机文件系统。如果读者正在开发新的
Docker应用程序,请考虑使用命名的卷。
三、卷的创建
Docker Volume Create 命令详解
命令格式:
docker volume create [OPTIONS] [VOLUME]
功能:
创建一个新的数据卷。数据卷用于持久化存储和容器间共享数据。
参数说明
| 参数 | 缩写 | 说明 |
|---|---|---|
--driver |
-d |
指定卷驱动名称。默认值为 local(使用宿主机的本地文件系统)。• 官方卷驱动文档:https://docs.docker.com/storage/volumes/ |
--label |
为卷设置元数据(标签),用于对卷进行分类或标记。 | |
--name |
指定卷的名称。 • 重要:当使用了 --name 参数时,可以省略命令末尾的 [VOLUME] 参数,两者的作用完全相同。 |
|
--opt |
-o |
指定卷驱动的选项参数。这些选项因驱动而异(例如,对于 local 驱动,可以设置设备类型、文件系统等)。 |
[VOLUME] 参数说明
-
[VOLUME]参数代表要创建的卷名称。 -
如果既没有使用
--name选项,也没有在命令末尾指定[VOLUME],Docker 会创建一个匿名卷,并为其生成一个随机的、唯一的名称。 -
卷名称必须在所有 Docker 卷中是唯一的。
root@debase:~# docker volume create my-vol1
my-vol1
root@debase:~# docker volume create --name my-vol2
my-vol2
四、卷列表查看
Docker Volume LS 命令详解
命令格式:
docker volume ls [OPTIONS]
功能:
列出当前 Docker 环境中的所有数据卷。
命令示例与输出解析
执行命令:
docker volume ls
典型输出:
root@debase:~# docker volume ls
DRIVER VOLUME NAME
local 2ca4997ef5fd25d79528143b678f442ad3f5d672aeaccb99a77c4a42f156cceb
local 8b93eed1ae5756093efb497eb1776d71cf8b688be860749a97ec335c741f61c4
local 9b28768f72fee829dfd9d79c7f3fd0e397575ddeaf4bda78da692a73e011b566
local 5567a9a396cbd723fc1b61b65c3f4b8ebe6b88b3d82a310a0608414da43b6967
local ea1e74d7322e2452f88bbc696496bd222796c5e677413d7bc4b83dd149641f29
local ec5104b8730b5b0cf7268d7c15099af5a5e338874a0f7b90b367f71403f644d1
local f25d818354514eacad8a9c0f2c2cf1c955b269d4c1aa54594f6640a42582392d
local fc5116202752352927aab83e93bc750a19f50e856667005238ef927dd1bd82bf
local my-vol1
local my-vol2
输出字段说明:
| 字段 | 说明 |
|---|---|
DRIVER |
创建该卷时使用的卷驱动。 |
VOLUME NAME |
卷的唯一名称。 |
输出内容分析:
-
匿名卷:
-
前两个卷的名称是一长串随机哈希值(如
2ba6c99d9d1c...)。 -
这些是匿名卷,由 Docker 在未指定名称时自动生成。
-
它们的卷驱动也是
local。
-
-
具名卷:
-
最后两个卷
my-vol1和my-vol2是用户通过docker volume create [卷名]命令创建的具名卷。 -
从输出中可以清楚地看到,这些具名卷使用的卷驱动同样是默认的
local驱动。
-
常用可选参数
| 参数 | 说明 |
|---|---|
--filter 或 -f |
使用过滤器来列出符合条件的卷。例如:-f name=my-vol |
--format |
使用 Go 模板格式化输出内容。例如:--format "{{.Name}} ({{.Driver}})" |
--quiet 或 -q |
仅显示卷的名称,不显示表头和其他信息。 |
使用示例:
-
仅显示卷名:
docker volume ls -q root@debase:~# docker volume ls -q 2ca4997ef5fd25d79528143b678f442ad3f5d672aeaccb99a77c4a42f156cceb 8b93eed1ae5756093efb497eb1776d71cf8b688be860749a97ec335c741f61c4 9b28768f72fee829dfd9d79c7f3fd0e397575ddeaf4bda78da692a73e011b566 5567a9a396cbd723fc1b61b65c3f4b8ebe6b88b3d82a310a0608414da43b6967 ea1e74d7322e2452f88bbc696496bd222796c5e677413d7bc4b83dd149641f29 ec5104b8730b5b0cf7268d7c15099af5a5e338874a0f7b90b367f71403f644d1 f25d818354514eacad8a9c0f2c2cf1c955b269d4c1aa54594f6640a42582392d fc5116202752352927aab83e93bc750a19f50e856667005238ef927dd1bd82bf my-vol1 my-vol2 -
过滤出名称中包含 "my" 的卷:
docker volume ls -f name=my root@debase:~# docker volume ls -f name=my DRIVER VOLUME NAME local my-vol1 local my-vol2 -
自定义格式输出:
docker volume ls --format "Volume: {{.Name}}\tDriver: {{.Driver}}" root@debase:~# docker volume ls --format "Volume: {{.Name}}\tDriver: {{.Driver}}" Volume: 2ca4997ef5fd25d79528143b678f442ad3f5d672aeaccb99a77c4a42f156cceb Driver: local Volume: 8b93eed1ae5756093efb497eb1776d71cf8b688be860749a97ec335c741f61c4 Driver: local Volume: 9b28768f72fee829dfd9d79c7f3fd0e397575ddeaf4bda78da692a73e011b566 Driver: local Volume: 5567a9a396cbd723fc1b61b65c3f4b8ebe6b88b3d82a310a0608414da43b6967 Driver: local Volume: ea1e74d7322e2452f88bbc696496bd222796c5e677413d7bc4b83dd149641f29 Driver: local Volume: ec5104b8730b5b0cf7268d7c15099af5a5e338874a0f7b90b367f71403f644d1 Driver: local Volume: f25d818354514eacad8a9c0f2c2cf1c955b269d4c1aa54594f6640a42582392d Driver: local Volume: fc5116202752352927aab83e93bc750a19f50e856667005238ef927dd1bd82bf Driver: local Volume: my-vol1 Driver: local Volume: my-vol2 Driver: local
五、卷默认存储位置
Docker 卷的存储位置与权限
默认存储路径
Docker 创建的卷默认存储在宿主机的以下目录中:
/var/lib/docker/volumes/
目录权限与访问
-
Docker 管理:该目录及其内容由 Docker 守护进程直接管理。
-
非 Docker 进程不应修改:为了确保数据的一致性和可靠性,任何非 Docker 进程(如常规的用户应用程序或脚本)都不应直接修改该文件系统中的内容。
-
访问权限:因此,该目录对普通用户没有查看权限。
访问示例:
必须使用 sudo 权限才能列出该目录的内容。
sudo ls /var/lib/docker/volumes/
典型输出:
root@debase:~# ls /var/lib/docker/volumes/
2ca4997ef5fd25d79528143b678f442ad3f5d672aeaccb99a77c4a42f156cceb ec5104b8730b5b0cf7268d7c15099af5a5e338874a0f7b90b367f71403f644d1
5567a9a396cbd723fc1b61b65c3f4b8ebe6b88b3d82a310a0608414da43b6967 f25d818354514eacad8a9c0f2c2cf1c955b269d4c1aa54594f6640a42582392d
8b93eed1ae5756093efb497eb1776d71cf8b688be860749a97ec335c741f61c4 fc5116202752352927aab83e93bc750a19f50e856667005238ef927dd1bd82bf
9b28768f72fee829dfd9d79c7f3fd0e397575ddeaf4bda78da692a73e011b566 metadata.db
backingFsBlockDev my-vol1
ea1e74d7322e2452f88bbc696496bd222796c5e677413d7bc4b83dd149641f29 my-vol2
目录结构解析
| 目录项 | 类型 | 说明 |
|---|---|---|
my-vol1, my-vol2 |
目录 | 这些目录的名称与通过 docker volume create 命令创建的具名卷的名称完全一致。每个卷的数据通常存储在其对应的目录下的 _data 子目录中。 |
2ba6c99d9d1c..., 5dd4508797e0... |
目录 | 这些目录的名称与通过 docker volume ls 看到的匿名卷的随机哈希名称完全一致。 |
metadata.db |
文件 | Docker 用于管理卷的元数据库文件。它记录了卷的元信息(如名称、驱动、标签等),不应手动修改此文件。 |
| (其他文件) | 文件 | 可能还包含由 Docker 或卷驱动维护的其他内部文件和块文件。 |
关键观察:
/var/lib/docker/volumes/目录下的子文件夹名称,与通过docker volume ls命令列出的 VOLUME NAME 是完全一致的。每一个卷(无论是具名卷还是匿名卷)都在此目录下有一个对应的文件夹。
六、卷删除
Docker 卷删除命令详解
Docker 提供了两个命令来删除卷,用于不同的场景。
1. docker volume rm - 删除指定卷
命令格式:
bash
docker volume rm [OPTIONS] VOLUME [VOLUME...]
参数说明:
| 参数 | 说明 |
|---|---|
VOLUME [VOLUME...] |
指定一个或多个要删除的卷名称。 |
-f, --force |
强制移除一个或多个卷。 |
实践示例:移除 my-vol2 卷
# 删除指定的 my-vol2 卷
rz@demo:~$ docker volume rm my-vol2
my-vol2
# 查看删除后的卷列表,确认 my-vol2 已不存在
rz@demo:~$ docker volume ls
DRIVER VOLUME NAME
local 2ba6c99d9d1c7225f052c55c4d9c62eb0e895ff81cb0b36928fd8e92022aed35
local 5dd4508797e0950e46e171e15ba79998130dfb78bdd0325fb2f0e09b298ee986
...
local my-vol1
2. docker volume prune - 清理未使用的卷
命令格式:
docker volume prune [OPTIONS]
参数说明:
| 参数 | 说明 |
|---|---|
-f, --force |
不进行确认提示,直接移除所有未使用的卷。 |
功能说明:
移除所有未被任何容器使用的本地卷。
实践示例:移除系统内未使用的卷
# 执行清理命令,系统会提示确认
rz@demo:~$ docker volume prune
WARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
# 显示被删除的卷列表
Deleted Volumes:
8060d803c478443df41b16d2ef0064efea5ba9882cb2e72269867e9d34eb8283
...
2ba6c99d9d1c7225f052c55c4d9c62eb0e895ff81cb0b36928fd8e92022aed35
...
5dd4508797e0950e46e171e15ba79998130dfb78bdd0325fb2f0e09b298ee986
...
# 显示回收的磁盘空间
Total reclaimed space: 2.022GB
# 查看清理后的卷列表
rz@demo:~$ docker volume ls
DRIVER VOLUME NAME
local my-vol1
关键区别总结
| 命令 | 删除对象 | 特点 |
|---|---|---|
docker volume rm |
指定的一个或多个卷 | 精确删除,需要明确知道要删除的卷名 |
docker volume prune |
所有未被使用的本地卷 | 批量清理,主要用于释放磁盘空间 |
重要观察:
单独创建的具名卷
my-vol1如果没有被任何容器使用,在执行docker volume prune时不会被自动删除。这是因为prune命令主要针对的是匿名卷和未被引用的卷,而手动创建的具名卷即使未被使用,通常也需要显式删除。
七、绑定挂载
Docker 绑定挂载详解与实践
同使用卷一样,可以在创建启动容器时,通过 --mount 或 --volume 参数使用绑定挂载。
参数语法详解
1. -v 或 --volume 参数
语法格式:
-v <第一字段>:<第二字段>:<第三字段>
| 字段 | 说明 | 注意 |
|---|---|---|
| 第一字段 | 宿主机上文件或目录的绝对路径 | 与卷挂载的第一字段(卷名)有重要区别 |
| 第二字段 | 容器内挂载的文件或目录路径 | 可以为文件 |
| 第三字段 | 逗号分隔的选项列表(可选) | 如 ro(只读)、z、Z |
关于
z和Z选项:用于配置 SELinux 标签,参考 Docker 官网文档
2. --mount 参数
语法格式:
--mount <key1>=<value1>,<key2>=<value2>,...
| 键 (key) | 说明 | 示例值 |
|---|---|---|
type |
挂载类型:bind, volume, tmpfs |
bind |
source 或 src |
主系统上文件或目录的绝对路径 | $HOME/data_bind |
destination 或 dst 或 target |
容器内的目标路径 | /var/lib/mysql |
readonly |
可选,容器以只读方式使用 | - |
注意:
--mount参数不支持用于修改 SELinux 标签的z或Z选项
重要行为区别
| 场景 | -v 参数行为 |
--mount 参数行为 |
|---|---|---|
| 挂载不存在的路径 | 自动创建相应的目录(对于文件也会创建目录) | 抛出异常错误,操作失败 |
实践案例
【实践07】使用 --mount 参数进行绑定挂载
1) 创建目录和容器
# 创建宿主机目录(必须手动创建)
rz@demo:~$ mkdir ~/data_bind
rz@demo:~$ ls
data_bind debian-src docker-ce scripts
# 创建容器并使用绑定挂载
rz@demo:~$ docker run -d --name mysql-studk6 \
--mount type=bind,source=$HOME/data_bind,target=/var/lib/mysql \
-p 3318:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.40-debian
9bc201ed0715968cf664c982c95bbca6fd196a88bdf8d7720e54c58af60c75e8
rz@demo:~$ docker ps
CONTAINER ID IMAGE STATUS PORTS NAMES
9bc201ed0715 mysql:8.0.40-debian Up 11 seconds ...3318... mysql-studk6
验证挂载:
rz@demo:~$ ls ~/data_bind/
auto.cnf client-key.pem '#innodb_temp' server-key.pem
binlog.000001 '#ib_16384_0.dblwr' mysql sys
binlog.000002 '#ib_16384_1.dblwr' mysql.ibd undo_001
binlog.index ib_buffer_pool performance_schema undo_002
ca-key.pem ibdata1 private_key.pem
ca.pem ibtmp1 public_key.pem
client-cert.pem '#innodb_redo' server-cert.pem
注意:使用
--mount参数,必须手动先创建宿主机目录,并且给出绝对路径。
2) 创建数据库并验证持久化
# 连接 MySQL 服务创建数据库
rz@demo:~$ mysql -h 127.0.0.1 -P3318 -uroot -p123456
MySQL [(none)]> create database studk_test;
Query OK, 1 row affected (0.005 sec)
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| studk_test |
| sys |
+--------------------+
5 rows in set (0.003 sec)
MySQL [(none)]> exit;
# 停止并删除容器
rz@demo:~$ docker stop mysql-studk6
mysql-studk6
rz@demo:~$ docker rm mysql-studk6
mysql-studk6
# 验证数据持久化
rz@demo:~$ ls ~/data_bind/
auto.cnf client-key.pem mysql studk_test
binlog.000001 '#ib_16384_0.dblwr' mysql.ibd sys
...
删除容器后,所创建的
studk_test数据库在宿主机目录中持久化存储下来了。
【实践08】以只读方式绑定挂载
1) 准备宿主机目录和文件
rz@demo:~$ mkdir ~/data_bind2
rz@demo:~$ echo "Hello, World!" > ~/data_bind2/test.txt
rz@demo:~$ cat ~/data_bind2/test.txt
Hello, World!
2) 创建容器并以只读方式绑定挂载
rz@demo:~$ docker run -d --rm --name mysql-studk7 \
-v $HOME/data_bind2:/root:ro \
-p 3320:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:8.0.40-debian
919d8d1f0f66f8c99a4041b14ca3b16db680e94407182de72d00382651d15e55
rz@demo:~$ docker ps
CONTAINER ID IMAGE STATUS PORTS NAMES
919d8d1f0f66 mysql:8.0.40-debian Up 2 seconds ...3320... mysql-studk7
3) 验证只读绑定
# 进入容器
rz@demo:~$ docker exec -it mysql-studk7 /bin/bash
# 查看挂载的文件
root@919d8d1f0f66:/# cd /root/
root@919d8d1f0f66:~# ls
test.txt
# 尝试删除文件(应该失败)
root@919d8d1f0f66:~# rm test.txt
rm: cannot remove 'test.txt': Read-only file system
root@919d8d1f0f66:~# exit
exit
# 清理容器
rz@demo:~$ docker stop mysql-studk7
mysql-studk7
rz@demo:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
在容器内以 root 权限删除
test.txt,系统提示"只读文件系统",验证只读绑定成功。
关键总结
-
绑定挂载 vs 卷挂载:绑定挂载使用宿主机路径,卷挂载使用卷名称
-
路径要求:
--mount必须手动创建宿主机目录,-v会自动创建 -
只读保护:使用
ro选项或readonly键可以防止容器修改宿主机文件 -
数据持久化:绑定挂载的数据直接保存在宿主机文件系统中,生命周期独立于容器
八、总结与预告
1、下节课程预告
每天半小时,轻松学Docker第七篇:对象查询与资源配额
更多推荐


所有评论(0)