当前位置: 首页
系统平台
Device Mapper插件改变Docker容器大小方法详解

Device Mapper插件改变Docker容器大小方法详解

热心网友 时间:2026-06-16
转载

在 CentOS、RHEL、Fedora 或其他默认缺少 AUFS 支持的 Linux 发行版上部署 Docker 时,Device Mapper 存储驱动几乎是必须使用的方案。一旦将其设为默认存储后端,所有容器都会被存储在一个 100GB 的稀疏文件中,且每个容器默认仅有 10GB 的容量上限。在

在 CentOS、RHEL、Fedora 或其他默认缺少 AUFS 支持的 Linux 发行版上部署 Docker 时,Device Mapper 存储驱动几乎是必须使用的方案。一旦将其设为默认存储后端,所有容器都会被存储在一个 100GB 的稀疏文件中,且每个容器默认仅有 10GB 的容量上限。在实际生产环境中,这个限制往往让人头疼——要么是存储池不够大,要么是单个容器空间捉襟见肘。本文要探讨的就是如何突破这一限制,同时将容器的存储迁移到指定分区或 LVM 卷上,从而让性能管理和数据规划更加灵活。

Device Mapper 的工作原理

要真正理解我们要做的操作,先得搞清 Device Mapper 驱动的工作机制。它基于 Device Mapper 的“精简配置”(thin provisioning)特性,本质上是对目标块设备进行快照管理。所谓“精简”,就是允许超额分配:拥有一个(通常很大的)可用存储块池,然后从这个池中创建任意大小的块设备(虚拟磁盘)。只有在实际写入数据后,对应的存储块才会被标记为已用,并从池中扣除。

这意味着可以非常灵活地配置——在一个 100GB 的池里创建上千个 10GB 的卷,甚至在一个 1GB 的池里创建 100TB 的卷,只要实际写入的块总量不超过池容量,系统就不会报错。此外,精简配置还支持快照:可以随时创建已有卷的浅拷贝。从用户角度看,就像有两个完全相同的卷,各自独立修改,但存储空间并不会翻倍——只有真正发生变化的块才会从池中额外分配。

从实现层面看,“精简配置”实际上使用了两个存储设备:一个大的存储块池,以及一个小型的元数据设备。元数据中记录了所有卷、快照,以及每个卷或快照的块到存储池中物理块的映射关系。

当 Docker 使用 Device Mapper 存储驱动时,它会在 /var/lib/docker/devicemapper/devicemapper/data/var/lib/docker/devicemapper/devicemapper/metadata 下创建两个文件(如果不存在)。这两个文件分别扮演存储池和元数据的角色。好处是免安装、零配置——无需额外分区或 LVM 就能直接运行。但缺点同样明显:存储池默认只有 100GB,而且是由稀疏文件支持的。从磁盘利用效率上看,稀疏文件表现不错(就像精简池中的卷,一开始很小,写多少占多少),但从性能角度看则不太友好——VFS 层会引入额外开销,尤其是在“首次写入”时。

在探讨如何调整单个容器大小之前,先来看看如何为整个池扩容。

我们需要一个更大的存储池

警告:以下操作会删除所有容器和镜像。请务必提前备份重要数据!

如前所述,Docker 在启动时会检查数据和元数据文件是否存在,不存在则自动创建。所以解决方案很简单:在 Docker 启动前,自己手动创建这些文件。

  1. 停止 Docker 守护进程——我们需要重新配置存储后端,运行时删除文件会引发问题。
  2. 清空 /var/lib/docker。再次警告:这会移除所有容器和镜像。
  3. 创建存储目录:
    mkdir -p /var/lib/docker/devicemapper/devicemapper
  4. 创建你的存储池:
    dd if=/dev/zero of=/var/lib/docker/devicemapper/devicemapper/data bs=1G count=0 seek=250
    这条命令会生成一个 250GB 的稀疏文件。注意使用 seek=250 而非 count=250,后者会创建普通文件(占用完整 250GB 真实磁盘空间)。
  5. 重启 Docker 守护进程。提示:如果系统本身支持 AUFS,Docker 默认会优先使用它;若要强制使用 Device Mapper,启动时加上 -s devicemapper 选项。
  6. docker info 检查 Data Space Total 的值是否正确。

我们需要一个更快的存储池

警告:同样会删除所有容器和镜像。务必将重要镜像推送到 registry,将容器中的关键数据备份出来。

要获得更好的性能,最简单的办法是用真实块设备替代基于文件的循环设备。假设有一块全新的硬盘 /dev/sdb,你想将其全部用于容器存储,操作步骤几乎相同:

  1. 停止 Docker 守护进程。
  2. 移除 /var/lib/docker(似曾相识吧?)。
  3. 创建存储目录:
    mkdir -p /var/lib/docker/devicemapper/devicemapper
  4. 在目录下创建指向设备的数据软链接:
    ln -s /dev/sdb /var/lib/docker/devicemapper/devicemapper/data
  5. 重启 Docker。
  6. docker info 验证 Data Space Total 是否正确。

使用 RAID 和 LVM

如果你手头有多块同型号的磁盘,可以通过软件 RAID10 将它们合并成一个逻辑设备,然后链接到 /dev/md 设备。另一个更灵活的方案是把磁盘(或 RAID 阵列)放入 LVM 物理卷,再创建两个逻辑卷:一个用于数据,一个用于元数据。元数据卷的最佳大小没有硬性规定,但建议从数据池的 1% 左右开始尝试。

操作思路与前两步一致:停止 Docker,移除数据目录,创建指向 /dev/mapper 设备的符号链接,重启 Docker。关于 LVM 的具体用法,可以参考 LVM 相关文档,这里不再赘述。

扩容容器根文件系统

默认情况下,使用 Device Mapper 存储驱动时,所有镜像和容器都从一个初始 10GB 的文件系统中创建。下面来看如何让容器拥有更大的根文件系统。

先用 Ubuntu 镜像创建一个容器,不需要运行任何程序,只要文件系统存在即可。为了演示,我们在容器里执行 df -h / 查看根分区大小:

$ docker run -d ubuntu df -h /
4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603

接下来需要以 root 身份操作 Device Mapper 中的卷信息。所有以 # 开头的命令都必须用 root 执行;其他命令(以 $ 开头)只要有 Docker socket 访问权限即可。

先查看 /dev/mapper,会看到一个对应容器文件系统的符号链接,命名格式为 docker-X:Y-Z- 开头:

# ls -l /dev/mapper/docker-*-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603
lrwxrwxrwx 1 root root 7 Jan 31 21:04 /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603 -> ../dm-8

记下这个完整名称,后面会用到。先查看当前卷的设备映射表:

# dmsetup table docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603
0 20971520 thin 254:0 7

第二个数字是设备大小,表示 512 字节扇区的数量——当前值正好略高于 10GB。计算一下一个 42GB 的卷需要多少扇区:

$ echo $((42*1024*1024*1024/512))
88080384

精简快照目标有一个特别的性质:它不会限制卷的大小。刚创建的精简卷使用 0 个块,写入时才会从共用池中分配。你可以写 0 块,也可以写 10 亿块,这与精简目标无关——真正限制文件系统大小的,是 Device Mapper 表本身。所以我们要做的,就是加载一张几乎完全相同的新表,只是扇区数加大了。

旧表是 0 20971520 thin 254:0 7。我们只改第二个数字,其余值必须原封不动保留(你的卷可能不是 7,一定要用正确的数值)。

# echo 0 88080384 thin 254:0 7 | dmsetup load docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603

现在激活新表:

# dmsetup resume docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603

再次查看表信息,应该已经变成新的扇区数量了。块设备扩容完成后,还需要调整文件系统大小,用 resize2fs 即可:

# resize2fs /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603
resize2fs 1.42.5 (29-Jul-2012)
Filesystem at /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603 is mounted on /var/lib/docker/devicemapper/mnt/4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 3
The filesystem on /dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603 is now 11010048 blocks long

作为可选验证步骤,重启容器并检查空闲空间:

$ docker start 4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603
$ docker logs 4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603
df: Warning: cannot read table of mounted file systems: No such file or directory
Filesystem      Size  Used A vail Use% Mounted on
-               9.8G  164M  9.1G   2% /
df: Warning: cannot read table of mounted file systems: No such file or directory
Filesystem      Size  Used A vail Use% Mounted on
-                42G  172M   40G   1% /

想把这个过程自动化?当然可以,下面是一段脚本示例:

CID=$(docker run -d ubuntu df -h /)
DEV=$(basename $(echo /dev/mapper/docker-*-$CID))
dmsetup table $DEV | sed "s/0 [0-9]* thin/0 $((42*1024*1024*1024/512)) thin/" | dmsetup load $DEV
dmsetup resume $DEV
resize2fs /dev/mapper/$DEV
docker start $CID
docker logs $CID

扩容镜像的局限性

遗憾的是,当前版本的 Docker 暂时没有提供简单的方法来扩容镜像。你可以把镜像对应的块设备扩容,然后基于它创建容器,但新容器并不会继承正确的大小。另外,如果你提交了一个很大的容器,最终生成的镜像也不会变大——这与 Docker 为镜像准备文件系统的方式有关。这意味着,如果某个容器真的超过了 10GB,在不借助其他技巧的情况下,很难直接将其正常提交为一个镜像。

总结

Docker 未来一定会提供更优雅的扩容方案——所需的代码改动其实很小。管理一个精简池和对应的元数据本身比较复杂(涉及多种操作流程和潜在的数据迁移,再加上我们直接擦除重建的方式,也未在本文中深入探讨),但今天提到的方法,已经足够解决大多数实际场景中的问题了。

来源:https://www.jb51.net/os/other/391438.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
Linux中如何配置指定系统时钟源进行校正

Linux中如何配置指定系统时钟源进行校正

如果你想确认当前 Linux 系统实际使用的是哪一种时钟源,直接执行 cat sys devices system clocksource clocksource0 current_clocksource 即可查看结果。常见返回值一般包括 tsc、hpet、acpi_pm 等;其中,tsc 通常具

时间:2026-08-12 06:56
CentOS 7修改系统网络接口默认传输速度方法

CentOS 7修改系统网络接口默认传输速度方法

如果只是想临时修改网卡传输速率,最直接、最常用的方法就是使用 ethtool。可以先通过 ip link show 确认网卡接口名称,再执行 ethtool ens33 查看当前链路状态以及网卡是否支持对应速率;确认支持后,运行 ethtool -s ens33 speed 100 duplex f

时间:2026-08-12 06:56
Linux文件系统快照计划配置方法与定时备份指南

Linux文件系统快照计划配置方法与定时备份指南

在 Linux 中配置文件系统快照计划,核心流程通常分为三步:先确认文件系统是否原生支持快照(如 Btrfs ZFS)或是否可借助 LVM 实现,再选择匹配的快照管理工具(如 Snapper、Timeshift 或 LVM 脚本),最后绑定合适的定时机制(systemd timer、cron 或 d

时间:2026-08-12 06:55
Mac同步失败后丢失文件怎么找回与恢复方法

Mac同步失败后丢失文件怎么找回与恢复方法

Mac iCloud同步中断致文件消失时,需立即关闭同步、从iCloud网页端抢救、提取本地缓存、重建同步索引并用终端定位残留;全程防止二次覆盖,优先保全数据。Mac上iCloud同步中断后,文档、备忘录、桌面文件突然消失,但本地磁盘里找不到原始副本,这种情况需要立即切断同步链路并分层排查——因为同

时间:2026-08-12 06:55
Mac远程桌面提示无权限访问的解决办法

Mac远程桌面提示无权限访问的解决办法

Mac 远程桌面一旦弹出“没有权限访问”,通常不能只盯着单一设置排查,而是要按权限、服务和账户状态逐步检查。先进入“系统设置→通用→共享→远程管理”,确认远程管理功能已经开启,并勾选“VNC显示程序可以使用密码控制屏幕”;然后检查目标账户是否已加入授权列表,以及当前是否处于活跃的图形界面会话中;最后

时间:2026-08-12 06:55
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜