【Docker存储】数据持久化与卷管理
·
一、 Docker 持久化
容器的“临时性”本质
Docker 容器基于 联合文件系统(Union File System) 运行:
- 底层是只读的镜像层(Image Layers)
- 顶层是一个可写的容器层(Container Layer),用于保存运行时产生的数据
关键问题:当容器被删除(
docker rm)或重建时,其可写层会完全丢失。这意味着:
- 数据库文件消失
- 用户上传的图片/附件丢失
- 日志、配置变更无法保留
结论:容器内部存储 ≠ 持久存储。
二、Docker 持久化的三种方式
Docker 提供三种机制实现持久化,如下所示:
| 方式 | 描述 | 适用场景 |
|---|---|---|
| 1. 数据卷(Volumes) | Docker 管理的专用目录,生命周期独立于容器 | 生产环境、数据库、通用持久化 |
| 2. 绑定挂载(Bind Mounts) | 将宿主机任意目录/文件挂载到容器内 | 配置热更新、代码调试 |
| 3. tmpfs 挂载 | 将数据存入宿主机内存(仅 Linux) | 临时敏感数据(如密钥缓存) |
三、数据卷(Volumes)
1. 数据卷
- 由 Docker 引擎创建和管理的特殊目录
- 默认存储在宿主机:
/var/lib/docker/volumes/<volume_name>/_data - 不依赖容器生命周期:即使所有使用该卷的容器都被删除,卷依然存在
2. 核心优势
- 跨容器共享:多个容器可同时挂载同一卷
- 易于备份与迁移:可通过临时容器打包卷内容
- 支持远程存储驱动:如 NFS、Ceph、AWS EBS(通过
-d指定驱动) - 权限自动处理:避免 SELinux 或权限问题(相比 Bind Mount)
3. 基本操作命令
# 创建命名卷
docker volume create my-data
# 查看卷列表
docker volume ls
# 查看卷详细信息(含宿主机路径)
docker volume inspect my-data
# 在运行容器时挂载卷
docker run -d \
--name web \
-v my-data:/usr/share/nginx/html \
nginx
删除未使用的卷(谨慎!)
17docker volume prune
4. 实战示例:持久化 MySQL 数据
# 1. 创建数据卷
docker volume create mysql-db
# 2. 启动 MySQL 并挂载卷到默认数据目录
docker run -d \
--name mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-v mysql-db:/var/lib/mysql \
mysql:8
# 3. 创建测试数据库
docker exec mysql mysql -uroot -p123456 -e "CREATE DATABASE test;"
# 4. 删除并重建容器(数据仍在!)
docker rm -f mysql
docker run -d --name mysql2 -e MYSQL_ROOT_PASSWORD=123456 -v mysql-db:/var/lib/mysql mysql:8
# 5. 验证数据存在
docker exec mysql2 mysql -uroot -p123456 -e "SHOW DATABASES;" # 包含 test
四、绑定挂载(Bind Mounts)——开发利器
1. 绑定挂载
- 将宿主机上的任意文件或目录直接挂载到容器内的指定路径
- 路径由用户指定,例如:
/home/user/app:/app
2. 使用方式
# 挂载当前目录到容器 /app
docker run -v $(pwd):/app -it ubuntu ls /app
# 挂载单个配置文件
docker run -v /host/nginx.conf:/etc/nginx/nginx.conf nginx
3. 适用场景
- 开发阶段:代码修改后容器内立即生效(热重载)
- 配置管理:动态更新 Nginx/Apache 配置
- 不推荐用于生产:依赖宿主机路径,可移植性差
4. 注意事项
- 宿主机路径必须绝对路径
- 若目标路径在容器中不存在,Docker 会自动创建为目录(即使你本意是挂载文件!)
- 权限问题常见(尤其在 SELinux 环境下),可加
:Z或:z选项(仅限 Linux)
五、持久化最佳实践
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 数据库(MySQL/PostgreSQL/Redis) | 命名卷(Volume) | 保证数据安全、支持备份 |
| Web 应用上传目录 | Volume | 用户头像、附件等需长期保存 |
| 日志收集 | Volume + 日志驱动(如 fluentd) | 避免日志撑爆容器磁盘 |
| 开发调试 | Bind Mount | 实现代码实时同步 |
| 敏感配置(密码、证书) | Docker Secrets(Swarm)或 ConfigMap(K8s) | 不应存入卷或镜像 |
安全建议
- 不要将卷挂载到
/或关键系统目录 - 避免多个容器并发写入同一文件(需应用层加锁)
- 定期备份重要卷(通过临时容器 tar 打包)
六、常见误区澄清
| 误区 | 正确理解 |
|---|---|
| “只要不删容器,数据就安全” | 容器可能因崩溃、升级、迁移被重建,仍会丢数据 |
“用 docker commit 可以保存数据” | commit 只保存镜像层,不包含 Volume 数据 |
| “Bind Mount 比 Volume 更灵活” | 灵活性带来的是可移植性和安全性的牺牲 |
| “Volume 存在宿主机上不安全” | Volume 路径受 Docker 管理,默认权限合理,比随意 Bind Mount 更安全 |
七、总结
Docker 持久化的核心思想是:将状态(State)与计算(Compute)分离。
- 数据卷(Volume) 是生产环境的标准答案
- 绑定挂载(Bind Mount) 是开发阶段的高效工具
- 不要依赖容器内部存储保存任何重要数据
通过合理使用持久化机制,你可以构建出:
- 高可用的应用(容器宕机重建不影响数据)
- 易维护的系统(数据可备份、可迁移)
- 云原生友好的架构(符合 12-Factor App 原则)
记住:“容器是牲口,不是宠物;数据是资产,必须外置。”
docker镜像制作
epel-aliyun.repo
CentOS-aliyun-lhr.repo

架构(符合 12-Factor App 原则)
记住:“容器是牲口,不是宠物;数据是资产,必须外置。”
docker镜像制作
epel-aliyun.repo
CentOS-aliyun-lhr.repo
[外链图片转存中…(img-gj6UjesU-1764158516438)]

更多推荐


所有评论(0)