Docker数据卷
Docker 数据卷学习笔记
1. 什么是数据卷
数据卷(volume)是一个虚拟目录,作为容器内目录与宿主机目录之间映射的桥梁。
1.1 数据卷的作用(以 Nginx 为例)
Nginx 中有两个关键目录:
- html:放置静态资源
- conf:放置配置文件
容器运行的 Nginx 所有文件都在容器内部,需利用数据卷将这两个目录与宿主机目录关联,方便操作。
1.2 数据卷的工作原理
- 创建两个数据卷:conf、html
- Nginx 容器内部的 conf 目录和 html 目录分别与两个数据卷关联
- 数据卷 conf 和 html 分别指向宿主机的
/var/lib/docker/volumes/conf/_data目录和/var/lib/docker/volumes/html/_data目录
通过这种关联(称为挂载),操作宿主机的对应目录就等同于操作容器内的对应目录。例如,将静态资源放入宿主机的 /var/lib/docker/volumes/html/_data 目录,就可被 Nginx 代理。
1.3 数据卷的默认存储路径
/var/lib/docker/volumes 是默认存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为 /数据卷名/_data。
1.4 为什么使用数据卷而非直接指向宿主机目录
- 直接指向宿主机目录会与宿主机强耦合,若切换环境,宿主机目录可能改变,而容器一旦创建,目录挂载无法修改,会导致容器无法正常工作。
- 容器指向数据卷(一个逻辑名称),数据卷再指向宿主机目录,可避免强耦合。若宿主机目录改变,只需修改数据卷与宿主机目录之间的映射关系即可。
不过,由于数据卷目录较深,不好寻找,通常也允许让容器直接与宿主机目录挂载而不使用数据卷。
2. 数据卷命令
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker volume create | 创建数据卷 | docker volume create |
| docker volume ls | 查看所有数据卷 | docs.docker.com |
| docker volume rm | 删除指定数据卷 | docs.docker.com |
| docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
| docker volume prune | 清除数据卷 | docker volume prune |
2.1 注意事项
容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,不能设置数据卷。且创建容器的过程中,数据卷会自动创建。
3. 教学演示环节
3.1 Nginx 的 html 目录挂载
首先创建容器并指定数据卷,通过
-v参数来指定数据卷:1
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
查看数据卷:
1
docker volume ls
结果:
1
2
3DRIVER VOLUME NAME
local 29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f
local html查看数据卷详情:
1
docker volume inspect html
结果:
1
2
3
4
5
6
7
8
9
10
11[
{
"CreatedAt": "2024-05-17T19:57:08+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]查看
/var/lib/docker/volumes/html/_data目录:1
ll /var/lib/docker/volumes/html/_data
可以看到与 nginx 的 html 目录内容一样,结果如下:
1
2
3总用量 8
-rw-r--r--. 1 root root 497 12月 28 2021 50x.html
-rw-r--r--. 1 root root 615 12月 28 2021 index.html进入该目录,并随意修改
index.html内容:1
2cd /var/lib/docker/volumes/html/_data
vi index.html打开页面,查看效果。
进入容器内部,查看
/usr/share/nginx/html目录内的文件是否变化:1
docker exec -it nginx bash
3.2 MySQL 的匿名数据卷
查看 MySQL 容器详细信息:
1
docker inspect mysql
关注其中
.Config.Volumes部分和.Mounts部分。.Config.Volumes部分:1
2
3
4
5
6
7
8
9{
"Config": {
// ... 略
"Volumes": {
"/var/lib/mysql": {}
}
// ... 略
}
}可以发现这个容器声明了一个本地目录,需要挂载数据卷,但是数据卷未定义,这就是匿名卷。
.Mounts部分:1
2
3
4
5
6
7
8
9
10
11{
"Mounts": [
{
"Type": "volume",
"Name": "29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f",
"Source": "/var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
}
]
}其中几个关键属性:
- Name:数据卷名称。由于定义容器未设置容器名,这里是匿名卷自动生成的名字,一串 hash 值。
- Source:宿主机目录
- Destination:容器内的目录
上述配置是将容器内的
/var/lib/mysql目录,与数据卷29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f挂载。于是在宿主机中就有了/var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data目录。这就是匿名数据卷对应的目录,其使用方式与普通数据卷没有差别。
查看该目录下的 MySQL 的数据文件:
1
ls -l /var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data
注意:每一个不同的镜像,创建容器后内部有哪些目录可以挂载,可参考 DockerHub 对应的页面。
4. 挂载本地目录或文件
数据卷的目录结构较深,操作不便。很多情况下,会直接将容器目录与宿主机指定目录挂载。
4.1 挂载语法
- 挂载本地目录:
-v 本地目录:容器内目录 - 挂载本地文件:
-v 本地文件:容器内文件
4.2 注意事项
本地目录或文件必须以 / 或 ./ 开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
- 例如:
-v mysql:/var/lib/mysql会被识别为一个数据卷叫 mysql,运行时会自动创建这个数据卷。 - 例如:
-v ./mysql:/var/lib/mysql会被识别为当前目录下的 mysql 目录,运行时如果不存在会创建目录。
4.3 教学演示:MySQL 容器本地目录挂载
删除并重新创建 mysql 容器,完成本地目录挂载:
- 挂载
/root/mysql/data到容器内的/var/lib/mysql目录 - 挂载
/root/mysql/init到容器内的/docker-entrypoint-initdb.d目录(初始化的 SQL 脚本目录) - 挂载
/root/mysql/conf到容器内的/etc/mysql/conf.d目录(MySQL 配置文件目录)
课前已准备好 mysql 的 init 目录和 conf 目录,以及对应的初始化 SQL 脚本(hmall.sql)和配置文件(hm.cnf,配置了 MySQL 的默认编码为 utf8mb4),并将整个 mysql 目录上传至虚拟机的 /root 目录下。
操作步骤:
删除原来的 MySQL 容器:
1
docker rm -f mysql
进入 root 目录:
1
cd ~
创建并运行新 mysql 容器,挂载本地目录:
1
2
3
4
5
6
7
8
9docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
mysql查看 root 目录,发现
~/mysql/data目录已经自动创建好了:1
ls -l mysql
结果:
1
2
3
4总用量 4
drwxr-xr-x. 2 root root 20 5月 19 15:11 conf
drwxr-xr-x. 7 polkitd root 4096 5月 19 15:11 data
drwxr-xr-x. 2 root root 23 5月 19 15:11 init查看 data 目录,会发现里面有大量数据库数据,说明数据库完成了初始化:bash
1
ls -l data
查看 MySQL 容器内数据:
进入 MySQL:
1
docker exec -it mysql mysql -uroot -p123
查看编码表:
1
show variables like "%char%";
结果(编码是 utf8mb4):plaintext
1
2
3
4
5
6
7
8
9
10
11
12+--------------------------+--------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | /usr/share/mysql-8.0/charsets/ |
+--------------------------+--------------------------------+
查看数据:
查看数据库:
1
show databases;
结果(hmall 是黑马商城数据库):
1
2
3
4
5
6
7
8
9
10+--------------------+
| Database |
+--------------------+
| hmall |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)切换到 hmall 数据库:
1
use hmall;
查看表:
1
show tables;
结果:
1
2
3
4
5
6
7
8
9
10
11
12+-----------------+
| Tables_in_hmall |
+-----------------+
| address |
| cart |
| item |
| order |
| order_detail |
| order_logistics |
| pay_order |
| user |
+-----------------+查看 address 表数据:
1
select * from address;
结果:
1
2
3
4
5
6
7
8
9+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| id | user_id | province | city | town | mobile | street | contact | is_default | notes |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
| 59 | 1 | 北京 | 北京 | 朝阳区 | 13900112222 | 金燕龙办公楼 | 李佳诚 | 0 | NULL |
| 60 | 1 | 北京 | 北京 | 朝阳区 | 13700221122 | 修正大厦 | 李佳红 | 0 | NULL |
| 61 | 1 | 上海 | 上海 | 浦东新区 | 13301212233 | 航头镇航头路 | 李佳星 | 1 | NULL |
| 63 | 1 | 广东 | 佛山 | 永春 | 13301212233 | 永春武馆 | 李晓龙 | 0 | NULL |
+----+---------+----------+--------+----------+-------------+---------------+-----------+------------+-------+
4 rows in set (0.00 sec)
-
感谢你赐予我前进的力量