1. 当Docker开始"吃硬盘"时

作为一名资深运维工程师,我经历过十几次凌晨三点被磁盘报警叫醒的惨痛经历。Docker就像个贪吃的小怪兽,容器日志、镜像层、匿名卷这些"零食"不知不觉就把存储空间啃得干干净净。上周我们的生产环境刚发生过一起因存储耗尽导致的容器雪崩,32个微服务连环崩溃的场面实在触目惊心。

2. Docker存储原理速览

(技术栈:CentOS 7 + Docker 20.10.21 + devicemapper存储驱动)

Docker默认使用/var/lib/docker作为数据目录,其中包含:

  • 镜像层(image layers)
  • 容器可写层(container writable layer)
  • 卷(volumes)
  • 构建缓存(build cache)

查看当前存储使用情况:

# 查看存储驱动类型
$ docker info | grep "Storage Driver"
Storage Driver: devicemapper

# 查看具体存储池信息(仅devicemapper驱动有效)
$ dmsetup status
docker-8:1-123456-pool: 0 209715200 thin-pool 91:00 91:00 32768 

3. 扩容方案详解

3.1 方案一:直接修改存储驱动配置

(适用场景:单机开发环境快速调整)

示例:将devicemapper的存储池从100GB扩展到200GB

# 停止Docker服务
$ systemctl stop docker

# 备份原数据(重要!)
$ cp -r /var/lib/docker /var/lib/docker_backup

# 删除旧存储配置
$ rm -rf /var/lib/docker/*

# 创建新的存储池
$ docker-storage-setup --storage-driver devicemapper \
    --storage-opt dm.basesize=20G \
    --storage-opt dm.loopdatasize=200G

# 启动服务并验证
$ systemctl start docker
$ docker info | grep "Pool Name"
 Pool Name: docker-8:1-123456-pool
 Data file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata

3.2 方案二:LVM动态扩容

(技术栈:LVM2 + XFS文件系统)

操作步骤:

# 创建物理卷
$ pvcreate /dev/sdb

# 扩展卷组
$ vgextend centos /dev/sdb

# 扩展逻辑卷
$ lvextend -L +100G /dev/centos/docker

# 调整文件系统
$ xfs_growfs /dev/centos/docker

# 验证扩容结果
$ df -h /var/lib/docker
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/centos-docker 200G   87G  113G  44% /var/lib/docker

3.3 方案三:外挂存储设备

示例:使用NFS网络存储

# 创建NFS卷
$ docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=192.168.1.100,rw \
    --opt device=:/data/nfs_share \
    nfs_volume

# 使用指定卷启动容器
$ docker run -d --name nginx_nfs \
    -v nfs_volume:/usr/share/nginx/html \
    nginx:latest

4. 存储管理进阶技巧

4.1 定时清理策略

# 自动删除未使用的镜像、容器、卷(危险操作!)
$ docker system prune --volumes --all --force

# 安全清理脚本示例
#!/bin/bash
# 保留最近3个镜像版本
docker image prune -a --filter "until=72h" --force
# 删除停止超过24小时的容器
docker container prune --filter "until=24h" --force
# 清理未使用的卷(需确认业务情况)
docker volume prune --force

4.2 存储配额管理

# 限制容器存储使用(XFS需要开启配额功能)
$ docker run -it --storage-opt size=10G ubuntu /bin/bash

# 查看配额使用情况
$ xfs_quota -x -c 'report -h' /var/lib/docker

5. 应用场景分析

5.1 开发测试环境

推荐方案:使用本地目录绑定挂载

$ docker run -v /mnt/ssd_data:/app/data redis:6

5.2 生产环境高可用集群

推荐架构:

  • 存储层:Ceph分布式存储
  • 编排层:Kubernetes CSI驱动
  • 数据层:MySQL容器使用独立SAN存储

6. 技术方案对比

方案 操作复杂度 扩容粒度 数据安全 适用场景
修改驱动配置 ★☆☆☆☆ 整盘调整 开发环境
LVM扩容 ★★★☆☆ 精确调整 物理服务器
外挂存储 ★★☆☆☆ 灵活扩展 云环境/集群
分布式存储 ★★★★☆ 无限扩展 极高 大规模生产环境

7. 避坑指南与注意事项

  1. 扩容前必须备份:某金融公司因直接扩容导致500GB交易数据丢失
  2. 文件系统选择:XFS支持在线扩容,ext4需要卸载
  3. 容器编排陷阱:K8s的emptyDir默认使用节点磁盘
  4. 云环境特殊限制:AWS EBS卷类型影响IO性能
  5. 日志管理规范:某电商平台曾因日志暴增导致存储爆炸

8. 实战经验总结

经过多年实战,我总结出存储管理的"三三法则":

  • 三个必须监控的指标:inode使用率、卷容量、IO延迟
  • 三种必备工具:Prometheus监控、Grafana仪表盘、ELK日志系统
  • 三个关键策略:分层存储、自动清理、容量预警