十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Docker 存储路径迁移实战:从系统盘迁移到数据盘的完整方案

Docker 存储路径迁移实战:从系统盘迁移到数据盘的完整方案 1. 为什么非要动 Docker 存储路径一个系统盘告警引发的迁移先说一个最常见的场景我用 1panel 面板跑了几年服务系统盘当初只分了 60G装完系统和面板后还剩 50G 左右。开始跑 Docker 觉得挺宽裕可容器越开越多镜像越拉越多突然有一天 1panel 首页直接标红磁盘使用率 97%。登录服务器一看/根分区已经满了docker system df显示镜像层和容器可写层占据了 30 多个 G全压在系统盘里。这不是个例很多用 1panel 的用户都踩过这个坑。默认情况下Docker 的数据目录在/var/lib/docker和系统挤在同一块盘上。你通过 1panel 面板创建的每个容器拉取的每个镜像构建镜像时产生的中间层还有容器的日志文件全都写在这个目录下。时间一长系统盘必然告急。这时候最稳妥的办法就是把 Docker 的存储路径整体迁移到大容量数据盘上。这篇博文就围绕这个需求完整走一遍从磁盘准备、数据同步到配置切换、容器恢复的实战流程顺便分享几个迁移之后必须做的优化项。这套操作适合谁用过 1panel、对 Docker 基本原理有了解但又没真正碰过存储迁移的运维和开发者以及所有面临系统盘容量焦虑的服务器管理员。整个过程不需要你精通底层文件系统也不需要重新创建容器关键是理解数据同步路径切换服务重启这条主线剩下的就是细心。2. 迁移前必修课磁盘挂载、数据摸底与方案选型2.1 先把数据盘准备好分区、格式化和挂载假设你已经在云厂商控制台或者物理机上挂载了一块新的数据盘比如 200G。登录服务器后先确认磁盘是否被系统识别lsblk如果看到类似vdb、sdb这样的设备存在但没有挂载点说明磁盘已经就绪接下来就是分区和格式化。云盘一般建议直接整块盘格式化不需要分区避免分区对齐和大小调整的麻烦。# 格式化文件系统选择 ext4 或 xfs 均可 mkfs.ext4 /dev/vdb # 创建挂载目录 mkdir -p /data # 挂载 mount /dev/vdb /data这里有个细节如果服务器重启手动挂载会失效。一定要写入/etc/fstab用 UUID 而不是设备名因为设备名在重启后可能变化。先查出 UUIDblkid /dev/vdb然后把下面这行加进/etc/fstabUUIDxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults 0 2建议先执行mount -a验证一下 fstab 没有写错再确认df -h能看到新盘。这一步做错的话重启后系统可能卡在挂载阶段进不去别问我怎么知道的。2.2 摸底当前 Docker 存储占用迁移前心里要有数改了存储路径之后原有数据必须原封不动跟过去所以迁移前要盘点清楚/var/lib/docker里到底有什么、各占多大空间。在 1panel 面板里能看到容器列表和镜像列表但具体的目录级占用要靠命令行du -sh /var/lib/docker/*正常会看到这几个目录containers/容器的配置文件和日志日志膨胀重灾区image/镜像分层数据体积通常最大volumes/具名数据卷业务数据在这里overlay2/容器可写层运行中容器产生的增量数据network/、buildkit/、swarm/等辅助目录顺便用docker system df看一眼镜像、容器、数据卷、构建缓存各自占了多少。这个数据有两个用途一是估算迁移需要多长时间二是迁移后方便对比验证数据是否完整。2.3 迁移方案怎么选rsync 是最稳妥的正解复制 Docker 数据目录的方式不止一种这里对比一下主流做法。直接cp -a的问题在于如果 Docker 服务没完全停干净或者复制过程中有进程还在写文件容易产生不一致。而tar打包再解包中间多了一步浪费时间和磁盘空间。最合理的方式是rsync它支持增量同步、保留权限、属主、时间戳、软链接等所有关键属性而且可以在 Docker 服务停止后先同步一遍再增量同步一遍把变化的数据缩小到最小窗口。提示Docker 数据目录中文件属性极其重要。容器运行时的用户映射、文件权限、软链接如果丢失恢复启动时会出现各种诡异问题。rsync 加-a参数就是为这个场景准备的。另外要确认 Docker 的存储驱动。使用docker info查看 Storage Driver 字段常见的是overlay2。overlay2 目录里全是硬链接和软链接rsync 默认处理硬链接的方式是复制独立文件这样会膨胀体积所以同步时必须加-H参数保留硬链接。这个细节很多人漏掉漏掉的后果是迁移后镜像层文件变得巨大。3. 完整迁移实操从停止服务到启动验证的全流程3.1 停止服务的顺序有讲究直接粗暴地systemctl stop docker也不是不行但用 1panel 管理的服务器上还跑着面板的监控和日志采集如果面板本身也依赖 Docker 工作负载stop 之后 1panel 会显示一堆容器异常状态这没关系等迁移完启动就恢复了。关键点是先停容器再停 Docker 服务。如果只是停掉 dockerd 守护进程容器进程可能会变成孤儿状态继续运行导致数据目录还在被写入。稳妥的顺序是# 通过面板或命令行停止所有运行中的容器 docker stop $(docker ps -q) # 确认容器全部退出 docker ps -a # 停止 Docker 服务 systemctl stop docker # 确认服务已完全停止 systemctl status docker这里有个小坑某些容器配置了restart: always你把容器 stop 后dockerd 还在运行的话它可能又把容器拉起来。所以要先把启动策略临时改成 no或者直接停掉全部容器后立刻systemctl stop docker两步之间不要隔太久。另外1panel 安装的 Docker 有两种服务管理方式一种是 systemd 管理一种是 1panel 自带 CLI 管理。绝大多数 Linux 发行版用的是 systemd所以systemctl是有效的。如果你不确定可以执行ps -ef | grep dockerd看进程的启动参数确认 pid 文件位置。3.2 数据同步rsync 参数逐个说清楚数据目录的新位置我建议放在/data/docker和挂载点/data区分开避免将来误操作挂载点本身。同步命令如下mkdir -p /data/docker rsync -aH --infoprogress2 /var/lib/docker/ /data/docker/解释一下参数-a归档模式等价于-rlptgoD保留软链接、权限、属主、属组、时间戳、设备文件-H保留硬链接overlay2 存储驱动必需--infoprogress2显示整体进度大目录同步时心里有底源目录末尾的斜杠/var/lib/docker/表示同步目录内容而非目录本身目标/data/docker/表示同步进这个目录同步时间取决于数据量和磁盘速度。以我这台机器为例原始数据 25G机械盘到机械盘大概跑了十几分钟SSD 会快很多。同步完成后强烈建议做一次校验du -sh /var/lib/docker /data/docker diff -r /var/lib/docker /data/docker /tmp/docker_diff.logdiff可能在 overlay2 目录里报一些文件差异只要数量很少且都集中在容器的临时文件比如 sockets、pid 文件问题不大。重点确认du -sh的总量差异在可接受范围内。3.3 修改 Docker 配置daemon.json 的>vi /etc/docker/daemon.json{ data-root: /data/docker }这里要注意有些教程会让你在 1panel 面板的设置 - Docker 配置里改面板确实提供了可视化编辑界面。但面板生成的配置是覆盖式的如果你原本有镜像加速、日志驱动等自定义配置一定先备份原文件再改。改完之后先执行dockerd --validate这个命令检查配置合法性没问题再启动。启动方式可以用 systemdsystemctl start docker启动后立刻检查两件事docker info | grep Docker Root Dir docker ps -a第一句确认 Docker Root Dir 已经是/data/docker第二句确认原有容器全部出现在列表中且状态是 Exited 而不是报错。确认无误后把之前 stop 的容器逐个启动或者在 1panel 面板里批量启动。3.4 验证业务可用性迁移成功不能只看容器状态容器起来了不代表迁移成功要验证数据完整性。这一步分三种情况第一种是数据库类容器MySQL、PostgreSQL、Redis连接上去执行一些查询或者触发一次备份确认数据写入读取正常。第二步是确认容器日志在持续输出没有报错信息。docker logs --tail 100 mysql_container第二种是 Web 服务类容器用 curl 访问一下健康检查接口确认服务响应正常。如果是 Nginx 反代后端的容器访问一下实际域名路径别只看端口通不通。第三种是挂载了数据卷的容器比如用-v /host/xxx:/container/xxx映射的目录确认宿主机目录里的文件内容没有变化容器内能看到同样的文件。特别是如果你之前用 1panel 建的站点文件映射目录可能在/opt/1panel下面这些目录不随 Docker 迁移而移动但要做一次确认。注意容器恢复启动后建议观察十分钟再离开。重点看系统日志/var/log/messages或者通过journalctl -u docker -f跟踪是否有 I/O 错误。如果数据盘是机械盘还要关注是否出现磁盘读写异常的高延迟。4. 迁移之后的优化让容器存储更健康、更可控4.1 日志轮转配置容器日志别再无限膨胀了迁移成功后最应该立刻做的一件事就是给 Docker 加日志轮转。/var/lib/docker/containers/id/*-json.log这个文件是每个容器的标准输出日志如果不加限制跑上几个月能膨胀到几个 G直接蚕食掉刚腾出来的磁盘空间。我之前踩过一次坑Nginx 容器的访问日志涨到 8 个 G 才知道。在daemon.json里加日志驱动配置{ data-root: /data/docker, log-driver: json-file, log-opts: { max-size: 50m, max-file: 10 } }max-size单个日志文件大小上限超过这个值就滚动max-file最多保留多少个日志文件加上当前文件最多 11 个这样单容器日志最大占用约 550M从根源上防止日志腐化磁盘。改完配置需要重启 Docker 服务新配置只对之后创建的容器生效。已经存在的容器1panel 里有重建容器功能或者在命令行 recreate 一下但注意重建容器会丢失网络配置和某些标注具体场景要评估。4.2 镜像和构建缓存治理定期清理别等满了再动手存储路径迁移后是整理镜像的好时机。docker system df一眼能看到哪些镜像占空间大哪些是悬空镜像dangling images即none标签。悬空镜像是构建过程中产生的中间层如果构建频繁这些中间层会越积越多。我用 1panel 的时候习惯在面板的镜像页面定期检查但命令行更高效# 清理悬空镜像 docker image prune -f # 清理所有未使用的镜像谨慎使用 docker image prune -a -f # 清理构建缓存 docker builder prune -f注意-a会删掉所有没有被容器引用的镜像如果之后要重新用某个旧镜像就得重新拉取或重新构建。生产环境慎用-a我一般只做悬空镜像清理和构建缓存清理。还有构建缓存用 Dockerfile 构建过镜像的人都知道每次RUN指令都会生成一层缓存。这些缓存在/var/lib/docker里的buildkit目录下占空间清理方式就是上面第三条命令。1panel 里也集成了清理功能位置在面板设置 - 磁盘管理附近点一下就行。4.3 数据卷分离让有状态数据走上独立路径迁移默认存储路径之后更进一步的优化思路是容器部署时直接把数据卷映射到单独的数据盘而不是依赖 Docker 默认目录。举个实际例子我用 1panel 部署 MySQL 时推荐用下面的方式创建容器docker run -d \ --name mysql8 \ -v /data/mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORDxxxx \ mysql:8.0挂载方式有两种一种是 bind mount宿主机路径直接映射到容器如上例另一种是 named volumeDocker 管理的卷。bind mount 的好处是路径清晰备份时直接拷贝对应目录就行。named volume 的好处是权限管理自动化但从迁移和排查的角度我还是更推荐 bind mount尤其是数据库这类关键服务。为什么因为 bind mount 把有状态数据和容器生命周期解耦了。以后就算 Docker 目录又满了、或者容器崩溃重建数据本身不在/var/lib/docker里影响范围就小得多。这个理念可以推广到所有有状态服务数据库、Redis 持久化、MinIO 对象存储、Nacos 配置等等。4.4 1panel 面板的备份机制与迁移后的快照策略1panel 面板本身提供了一键备份功能支持本地备份、阿里云 OSS、腾讯云 COS 等目标。迁移完成后建议立刻配置一套备份策略。我在面板里是这样设置的对存放数据的关键目录/data做定期备份同时将 1panel 自身的配置目录/opt/1panel也纳入备份范围备份目标选择对象存储或者另一块磁盘上的目录。为什么要这么干因为 Docker 数据目录之外1panel 自身的配置也很有价值。面板里创建的网站、数据库账号、运行环境、计划任务、面板设置全部存在/opt/1panel下面。如果整台机器出问题有了这两个目录的备份重建一台服务器后恢复起来非常快。1panel 的数据库页面也支持对 MySQL、PostgreSQL 等数据库进行定时备份备份结果存放在/opt/1panel/backup/database下。如果数据库容器本身已经在/data盘上挂了数据卷再做一层逻辑备份双重保险。迁移之后就把这些备份策略完善好前前后后也就一个多小时关键时刻能救命。5. 踩坑实录迁移过程中最容易翻车的几个细节5.1 容器启动后>cat /etc/systemd/system/docker.service.d/*.conf如果有--data-root参数修改或注释掉然后systemctl daemon-reload systemctl restart docker。1panel 安装的 Docker 一般不会有多余的 systemd override但如果是手动装的 Docker或者是通过脚本安装的这条一定要检查。5.2 rsync 同步后容器权限错乱如果你同步之后启动容器发现容器内用户无法读写某些文件、或者容器直接启动失败大概率是同步时没有保留属主属组。rsync 默认在 root 用户下执行如果是跨盘同步目标目录的属主可能全变成了 root。上面我提到的-a参数包含了-o保留属主和-g保留属组但前提是接收端的 rsync 进程有足够的权限去设置这些属性。有些情况下比如目标盘挂载时带了noacl参数或者同步时用了--chown强制改属主就会出问题。最快的排查方式是ls -n /var/lib/docker | head -20 ls -n /data/docker | head -20逐项对比属主、属组和权限是否一致。不一致的话重新执行 rsync如果依然无效检查目标盘挂载参数mount | grep /data正常情况下应该有rw,relatime等参数如果看到noexec、nosuid这类限制参数也可能会影响 Docker 正常启动。5.3 容器恢复后网络异常迁移存储路径本身不涉及网络配置但如果你在迁移过程中重新创建过容器、或者 Docker 服务重启后网桥重建可能出现容器 IP 变化。比如你之前通过固定 IP 访问某个容器重启后 IP 变了业务就断了。解决办法是在迁移前记录每个容器的 IP 信息docker inspect --format{{.Name}} {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} $(docker ps -q)迁移后对照检查如果发现 IP 变了更稳妥的做法是给容器绑定自定义网络并用容器名访问或者直接用--network host让容器共享宿主机网络。1panel 创建的应用默认都配置好了反代域名一般不会因为容器 IP 变化就直接挂掉但裸 docker run 起的自定义容器要注意。5.4 迁移到了新盘但 Docker 性能反而变差了如果新数据盘是普通云盘而不是 SSDDocker 的 I/O 性能可能比原来系统盘通常也是云盘差。特别是数据库类容器和构建镜像的场景I/O 吞吐量下降会很敏感。这里给两个建议。第一如果条件允许新数据盘优先选择 SSD 类型或者在高性能磁盘上单独建一个分区给 Docker 用。第二如果迁移后性能不可接受可以考虑用--storage-driver切换存储驱动比如把 overlay2 换成 fuse-overlayfs 或者直接改用 device mapper但这属于进阶操作对大多数场景不推荐overlay2 仍然是主流首选。另外一个很现实的点是迁移之后要用 1panel 的面板监控功能多观察一段时间的磁盘 I/O。1panel 的主机监控页有 IOPS 和读写速率曲线如果发现持续飙高再结合具体容器的负载情况定位瓶颈。5.5 1panel 面板界面和 Docker 命令行状态不一致这个现象偶尔会发生用命令行启动了一个容器但 1panel 面板里看不到或者面板里显示的状态和docker ps不一致。原因通常是 1panel 有自己的一套容器管理缓存没有实时同步。遇到这种情况不用重启面板在 1panel 容器页面右上角点一下刷新按钮一般就能解决。如果刷新后依然不一致大概率是 1panel 的数据库连接异常重启一下 1panel 服务即可systemctl restart 1panel总的来说这类问题不影响容器本身的运行纯属面板的展示层同步延迟不用过度担心。6. 迁移后的日常巡检建议存储路径迁移完成之后日常巡检比迁移本身更重要。我给自己定了一个简单的巡检清单分享出来供参考。每周看一次系统盘和数据盘的使用率关注 1panel 首页的监控曲线尤其注意数据盘的写入量每月看一次docker system df清理悬空镜像和构建缓存每季度做一次关键数据卷的备份恢复演练。迁移不是终点用一个可持续的存储治理机制才是真正让 Docker 环境健康运行的长久之计。如果你正准备给 1panel 环境做 Docker 存储迁移照着上面这套流程走大概率能一次成功而不翻车。我个人的体会是迁移本身的命令不到十条真正花时间的是迁移前的数据盘准备、迁移后的优化和验证。只要把备份-同步-切换-验证这条主线牢牢记住就不会出大问题。
返回列表