Docker 的镜像、容器层、卷、网络等状态默认都存储在 /var/lib/docker。很多服务器系统盘只划分几十 GB,当镜像和容器数量增加后,系统盘很容易被打满。删除不用的镜像只能暂时缓解,真正彻底的办法是把 Docker 数据根目录迁移到一块容量更大的数据盘。迁移的重点不是简单的文件复制,而是要保证 overlay2 存储驱动的目录结构、文件权限和时间戳不被破坏,同时让 Docker 服务在重启后能准确找到新位置。下面将按照停服、同步、改配置、重启验证的顺序详细说明。

一、迁移前先确认当前数据根目录和磁盘状态
执行任何迁移操作之前,第一步是确认当前 Docker 实际使用的数据根目录。Docker 不同版本、不同安装方式可能会把数据放在不同位置,不能只凭经验判断。使用 docker info 可以查看 Docker Root Dir,它会明确指出当前存储路径。
sudo docker info | grep "Docker Root Dir" sudo du -sh /var/lib/docker df -h /var/lib/docker lsblk
上面几条命令分别用来确认数据根目录路径、估算目录总大小、查看当前所在分区的剩余空间,以及列出磁盘和分区。如果新磁盘还没有分区和格式化,需要先完成这些操作。以一块新盘 /dev/sdb1 为例,可以格式化为 ext4 或 xfs,然后挂载到 /mnt/docker-data。对于 overlay2 存储驱动来说,ext4 和 xfs 都是稳定的选择,其中 xfs 还需要确认 ftype=1,否则 Docker 会拒绝启动。
确认目标路径之后,要确保该目录的权限和属主符合 Docker 运行要求。Docker 服务通常以 root 身份运行,目标目录也需要 root 所有。如果使用了 SELinux,还要注意新目录的上下文是否允许容器访问。迁移前最好记录当前 /var/lib/docker 的属主和权限,便于后续对照。
二、通过 daemon.json 修改 data-root 完成迁移
这是最推荐也是长期维护成本最低的方式。核心思路是先把旧数据完整复制到新目录,再告诉 Docker 引擎新的数据根目录在哪里。Docker 的守护进程配置通常位于 /etc/docker/daemon.json,通过其中的 data-root 字段可以指定新的存储位置。
首先需要停止 Docker 服务以及 socket,避免复制过程中有新的写入。停止服务后,原来的容器也会停止运行,因此建议在业务低峰期操作。接着创建目标目录,使用 rsync 保留权限、属主和时间戳进行同步。
sudo systemctl stop docker docker.socket sudo mkdir -p /mnt/docker-data sudo rsync -aP /var/lib/docker/ /mnt/docker-data/
注意源路径 /var/lib/docker/ 结尾带有斜杠,表示复制目录下的内容,而不是把整个 docker 目录复制成 /mnt/docker-data/docker。复制完成后可以先对比一下新旧目录的大小和文件数量。如果数据量很大,第一次复制可以先用 rsync -aP 完成全量同步,正式切换前再停止服务执行一次增量同步,减少停机时间。
接下来编辑 /etc/docker/daemon.json,加入 data-root 字段。如果文件已经存在,要保留原有配置,只新增或修改这个字段。下面是一个最小配置示例。
{
"data-root": "/mnt/docker-data",
"storage-driver": "overlay2"
}
保存后启动 Docker,再用 docker info 检查路径是否已经改变。确认新路径生效后,可以运行一个测试容器验证镜像拉取、容器启动和删除流程是否正常。生产环境建议先在单台机器验证完整流程,再批量迁移其他节点。
sudo systemctl start docker sudo docker info | grep "Docker Root Dir" sudo docker run --rm hello-world
如果启动失败,先检查 daemon.json 是否是合法的 JSON 格式,再查看 journalctl -u docker.service 的日志。常见错误包括路径不存在、目标目录权限不足、SELinux 阻止访问等。对于 SELinux 环境,可以执行 sudo restorecon -Rv /mnt/docker-data 恢复上下文,或者使用 semanage 为新路径添加规则。
三、软链接方案:不修改配置的快速迁移
某些场景下不方便修改 daemon.json,例如使用了外部编排平台、监控脚本固定读取 /var/lib/docker,或者希望迁移过程对 Docker 配置保持透明。此时可以使用符号链接方案,把原路径指向新磁盘上的真实目录。Docker 依然访问 /var/lib/docker,但实际读写发生在新的存储位置。
软链接迁移也需要先停止 Docker 服务。先把旧的 /var/lib/docker 改名为备份目录,再把备份内容同步到新位置,最后创建符号链接。这样无论 Docker 还是其他工具,看到 /var/lib/docker 仍然存在。
sudo systemctl stop docker docker.socket sudo mv /var/lib/docker /var/lib/docker.bak sudo mkdir -p /mnt/docker-data sudo rsync -aP /var/lib/docker.bak/ /mnt/docker-data/ sudo ln -s /mnt/docker-data /var/lib/docker sudo systemctl start docker
这种方式实施速度快,路径变化对上层应用透明,但它依赖一个符号链接指向新目录。如果后续维护人员不熟悉,可能会误认为 /var/lib/docker 是真实目录,或者出现重复挂载、删除软链接等误操作。同时,个别监控或备份程序如果使用 find 默认不跟随符号链接,可能看不到真实数据。总体而言,软链接适合临时迁移或无法修改 Docker 配置的环境,长期维护还是建议采用 data-root 方案。
四、迁移后验证与常见问题处理
迁移完成后的验证不能只看 docker info。需要从镜像、容器、数据卷三个维度确认数据完整性。首先运行 docker images 和 docker ps -a,确认镜像列表和容器记录没有丢失。然后启动一个已有的容器,检查它的运行状态和网络配置是否正常。如果使用了命名卷,也要确保卷中的数据仍然可读。
sudo docker images sudo docker ps -a sudo docker volume ls sudo ls -lah /mnt/docker-data
建议迁移后保留旧目录一段时间,不要立刻删除。可以把旧目录改名为 docker.bak,观察业务运行几天后再清理。这样可以提供回滚机会。如果使用的是 data-root 方案,回滚只需要把 daemon.json 中的路径改回原值并重启;如果使用的是软链接方案,则可以删除链接并移回旧目录。
常见问题之一是 daemon.json 格式错误,导致 Docker 无法启动。JSON 不允许尾随逗号,也不允许使用单引号。另一个问题是复制后文件属主发生变化,尤其是使用 cp 而不是 rsync -a 时,可能会出现 root 之外的属主,导致权限错误。还有一类问题与挂载有关:如果新目录只是临时挂载而没有写入 /etc/fstab,服务器重启后挂载消失,Docker 将无法找到数据。因此迁移后应确认新挂载点在重启后仍然存在。
如果迁移后容器可以启动但个别容器出现异常,可以查看容器日志,并检查是否有绝对路径依赖旧目录。Docker 本身对 data-root 的感知是全局的,只要路径设置正确,镜像和容器通常可以正常工作。迁移操作本身不会改变镜像 ID、容器 ID 或网络名称,因此对应用层基本透明。
Docker数据目录数据根目录迁移Docker存储修改时间:2026-10-05 10:49:44