容器存储
容器最初设计为「无状态」的运行环境。但现实中的应用程序总需要存储数据:数据库的文件、用户上传的内容、应用的配置文件。这些数据不能随着容器销毁而消失。
容器存储解决了这个问题——它为容器提供了持久化或临时的数据存储能力。
容器存储模型
核心概念
存储流:
- 容器内的进程写入挂载点
- 挂载层将请求转发到 Volume
- Volume 与实际存储后端交互
- 数据持久化到文件系统
临时存储 vs 持久存储
Docker Volume 命令
基本操作
创建数据卷
使用数据卷启动容器
数据卷维护
绑定挂载
绑定宿主机目录
Warning
绑定挂载的风险:
- 容器内的进程可以修改宿主机文件(安全风险)
- 宿主机路径必须存在,否则 Docker 会创建(权限可能不对)
- 不同平台的路径格式不同(Windows/macOS vs Linux) :::
存储驱动
工作原理
存储驱动对比
查看当前存储驱动
选择存储驱动
配置存储驱动(daemon.json)
:::info 生产环境建议:
- Linux:使用
overlay2(默认) - Windows:使用
windowsfilter - 特殊场景:需要考虑特定驱动的功能(如 ACL、快照)
现代 Docker 默认使用 overlay2,不需要额外配置。
数据持久化机制
命名卷
创建和管理命名卷
卷详情示例
只读挂载
配置只读挂载
tmpfs 内存存储
使用
tmpfs
容器存储最佳实践
分离应用层和数据层
Dockerfile
使用卷插件扩展存储
RexRay
数据库存储配置
PostgreSQL
存储权限
用户权限控制
指定容器用户
卷权限问题
常见的权限问题
Dockerfile
常见问题与反模式
问题一:匿名卷堆积
问题场景
问题:忘记使用命名卷,导致匿名卷堆积,难以清理。
正确做法:始终使用命名卷。
正确示例
问题二:挂载覆盖关键目录
问题场景
正确做法:
- 先检查宿主机路径是否存在
- 使用
ro模式挂载只读配置 - 考虑使用
docker cp或进入容器修改
替代方案:使用
问题三:混合使用多种存储方式
混乱的配置示例
问题:维护困难,难以追踪数据位置。
正确做法:统一存储策略,清晰区分数据用途。
清晰配置示例
问题四:生产环境使用绑定挂载
生产环境错误配置
问题:紧耦合宿主机,难以迁移和扩展。
正确做法:使用命名卷或云存储。
生产环境正确配置
存储监控
查看存储使用
检查卷使用情况
清理未使用的资源
权衡矩阵
延伸思考
容器存储看似简单,但有几个值得深入思考的问题:
- 数据备份策略:命名卷不会自动备份,需要外部机制
- 存储迁移:跨主机迁移容器时,数据是否可用?
- 性能优化:存储是否成为瓶颈?
数据备份策略示例
对于需要高性能、大容量或跨主机共享的存储,可以考虑:
- GlusterFS:分布式文件系统
- Ceph:统一的软件定义���储
- NFS:简单共享存储
- 云厂商存储服务:AWS EBS、GCP PD、Azure Disk
理解容器存储的原理和限制,才能设计出既高效又可靠的应用架构。