04 容器存储
常考主线:Storage Driver(管镜像层/容器层)→ 两种持久化方式 volume / bind mount → 容器间数据共享(含 volume container)。
一、整体存储机制(先分清三层)
| 机制 | 管理对象 | 数据是否持久 | 生命周期 |
|---|---|---|---|
| Storage Driver | 只读镜像层 + 可写容器层(CoW) | 不持久,适合无状态数据 | 容器删除,容器层随之删除 |
| Volume(数据卷) | Docker 管理的宿主机目录 | 持久化 | 独立于容器,删容器数据还在 |
| Bind Mount(绑定挂载) | 用户指定的宿主机目录/文件 | 持久化 | 独立于容器 |
核心结论:volume 和 bind mount 本质都是宿主机文件系统里的目录/文件 ,数据生命周期独立于容器,容器删除后数据依旧存在。
二、Storage Driver(存储驱动)
- 作用:管理镜像层和容器层,实现多层堆叠 + 合并统一视图;所有驱动都用"可堆叠层 + CoW 写时复制"。
- 查看当前驱动:
docker info。 - 选型建议:优先用 Linux 发行版默认驱动。
| 驱动 | 支持情况 |
|---|---|
| overlay2 | 当前所有主流 Linux 发行版首选、默认 |
| AUFS | 仅 Ubuntu/Debian 早期 |
| Device Mapper | 早期 CentOS/RHEL 推荐,现也支持 overlay2 |
| Btrfs | 仅 SLES |
| ZFS | Ubuntu 14.04+ |
| VFS | 仅测试,不用于生产 |
Storage Driver 管的容器层放**无状态(不需持久化)**数据;要持久化必须用 volume 或 bind mount。
三、Volume(数据卷)
1. 概念
- 由 Docker 统一管理,挂载时只需指定容器内挂载点,不用写宿主机源路径,Docker 自动建目录。
- 宿主机存放路径:
/var/lib/docker/volumes/<卷名>/_data。 -v挂载格式:<host path>:<container path>;用 volume 时省略 host path,只写容器路径。
2. 关键特性
- 数据独立于容器生命周期,删容器卷和数据仍在。
- 挂载时只指定挂载点,Docker 自动在 volumes 目录生成 mount 源。
- 挂载点指向容器内已有非空目录 时,该目录原有数据会被复制(copy)到 volume 中。
- 挂载点是空目录/不存在则自动创建;挂载不存在的卷会自动建卷。
- 可加 ro 参数让容器对卷只读。
3. 示例与命令
bash
# 只写容器路径 -> 匿名卷,Docker 自动生成一串卷ID目录
docker run -d -p 8080:80 -v /usr/local/apache2/htdocs httpd
docker volume create 卷名 # 手动创建卷(具名卷)
docker volume ls # 列出卷
docker volume rm 卷名 # 删除卷
docker volume inspect 卷名 # 查看卷挂载信息
docker inspect 容器 # 看 Mounts 字段,Type=volume
- 改宿主机
_data里的文件,容器内同步变化 → 实现主机↔容器数据共享。
四、Bind Mount(绑定挂载,重点)
1. 概念
- 把宿主机上已存在(或自动创建)的指定目录/文件 挂载到容器内,必须同时指定宿主机源路径 + 容器挂载点。
- 本质:一次 inode 替换过程------挂载点操作实际作用在被挂载的宿主机目录/文件上,容器内该挂载点原内容被隐藏。
2. 关键特性(常考,易和 volume 对比)
- 数据持久,删容器后宿主机数据仍在。
- 必须手写宿主机源路径(这也降低了可移植性,换机器路径可能不存在)。
- 挂载到容器内非空目录会"覆盖/隐藏"容器该目录原有内容(不是复制!);不想覆盖整个目录可只挂载单个文件。
- 宿主机源不存在时会自动创建(默认会按目录创建)。
- 加 ro 后容器只读,但宿主机仍可修改。
3. 示例
bash
# 宿主机 ~/htdocs 挂载到容器站点目录
docker run -d -p 8081:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
# 只读挂载
docker run -d -v /host/data:/data:ro centos
docker inspect看 Mounts,Type=bind。
五、Volume vs Bind Mount(高频对比)
| 对比项 | Volume | Bind Mount |
|---|---|---|
| 源路径位置 | Docker 管理:/var/lib/docker/volumes/ |
用户任意指定的宿主机路径 |
| 是否写 host path | 不用写,只写容器挂载点 | 必须写宿主机源:容器点 |
| 挂载到容器非空目录 | 把容器原内容复制进卷 | 覆盖隐藏容器原内容 |
| 管理方式 | docker volume 命令统一管理 | 由用户自己管理 |
| 可移植性 | 好(与宿主机路径解耦) | 差(依赖具体路径) |
| Mounts 中 Type | volume | bind |
| 共同点 | 都是宿主机上的目录/文件;数据都独立于容器持久保存;都支持 ro | 同左 |
六、数据共享(考点)
1. 主机 ↔ 容器
- bind mount:挂载宿主机目录/文件。
- volume:数据 copy 到卷目录,或直接往卷
_data目录 cp 文件。 - docker cp:在容器和主机之间复制文件(不走挂载也能传)。
bash
docker cp 主机文件 容器:容器路径
docker cp 容器:容器路径 主机路径
2. 容器 ↔ 容器
| 方式 | 做法 |
|---|---|
| bind mount 共享 | 多个容器 -v 挂载同一个宿主机目录 |
| volume 共享 | 多个容器挂载同一个卷 |
| volume container(数据卷容器) | 先做一个挂了卷的容器 vc,其他容器用 --volumes-from vc 引用它的挂载 |
3. volume container 示例(常考)
bash
# 1) 创建数据卷容器 vc(只 create 不用运行,是个挂了卷的普通容器)
docker create --name vc -v /root/htdocs/:/usr/local/apache2/htdocs httpd
# 2) 业务容器通过 --volumes-from 引用 vc 的全部挂载
docker run --name httpd3 -d -p 1003:80 --volumes-from vc httpd
docker run --name httpd4 -d -p 1004:80 --volumes-from vc httpd
- vc、httpd3、httpd4 的卷挂载信息一致,改共享目录内容,多个容器同步更新。
七、速记口诀
- Storage Driver 管层(无状态、随容器删);volume/bind 管持久数据(删容器不丢)。
- 首选驱动 overlay2 ,
docker info看驱动。 - volume 不写源路径、Docker 管、非空目录是"复制";bind 必写源路径、非空目录是"覆盖"。
- 两者本质都是宿主机目录,都支持 ro,数据都比容器活得久。
- 多容器共享:挂同一目录/同一卷,或用数据卷容器 +
--volumes-from。 - commit 不打包挂载数据;传零散文件用
docker cp。