一次 Docker overlay2 撑爆根分区的线上修复记录

本文最后更新于 2 天前

一次 Docker overlay2 撑爆根分区的线上修复记录

这次故障发生在一台 GPU 推理服务器上。

表面现象是磁盘满了,实际问题比“删点文件”复杂得多:Docker overlay2 占用失控、容器日志无限增长、部分已删除文件仍被进程持有,最后连 Docker 自己的清理命令都无法释放空间。

本文记录完整排查和修复过程。


1. 问题背景

服务器主要跑几个 AI 推理服务:

  • Triton Inference Server
  • TensorRT Engine 构建任务
  • Python 后处理服务
  • Nginx 网关
  • Prometheus Node Exporter

机器配置如下:

项目 配置
OS Ubuntu 22.04
Docker 27.x
文件系统 ext4
Docker Root Dir /var/lib/docker
GPU RTX 4090
推理框架 TensorRT / Triton
日志驱动 json-file

业务侧最早反馈是:

推理接口偶发 502,重启容器后短暂恢复,但十几分钟后再次异常。

这类问题很容易被误判成模型服务崩溃、GPU 显存不足、Nginx upstream 超时。实际根因在磁盘。


2. 现象与日志

首先看系统磁盘:

df -h
BASH

输出:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       197G  197G     0 100% /
tmpfs            32G  1.8M   32G   1% /run
/dev/sdb1       1.8T  628G  1.1T  37% /data
BASH

根分区已经 100%。

继续看 inode:

df -i
BASH

输出:

Filesystem       Inodes   IUsed     IFree IUse% Mounted on
/dev/sda1      13107200 12988401   118799  100% /
/dev/sdb1     122101760  2134419 119967341    2% /data
BASH

磁盘空间和 inode 都接近耗尽。

这时 Docker 状态已经不稳定:

docker ps
BASH

卡住十几秒才返回。

系统日志也开始报错:

journalctl -xe
BASH

关键日志:

systemd-journald[482]: Failed to write entry to /var/log/journal/...: No space left on device
dockerd[1361]: failed to register layer: write /var/lib/docker/image/overlay2/layerdb/tmp/write-set-xxxx: no space left on device
containerd[1228]: failed to create shim task: no space left on device
nginx[24918]: connect() failed (111: Connection refused) while connecting to upstream
TEXT

Triton 容器日志里也出现了写入失败:

docker logs triton-server --tail 100
BASH

输出:

E0515 03:17:42.918642 1 logging.cc:43] failed to flush log file: No space left on device
E0515 03:17:43.104811 1 model_repository_manager.cc:1297] failed to update model repository index
TEXT

到这里可以确定:

不是 GPU 问题,不是模型问题,而是根分区被 Docker 打满后引发的连锁故障。


3. 快速定位大目录

先看根目录下的空间分布:

sudo du -xhd1 / | sort -hr | head -20
BASH

输出:

188G    /
184G    /var
2.1G    /usr
1.2G    /opt
612M    /lib
TEXT

继续查 /var

sudo du -xhd1 /var | sort -hr | head -20
BASH

输出:

181G    /var/lib
2.7G    /var/log
312M    /var/cache
TEXT

再看 Docker 目录:

sudo du -xhd1 /var/lib/docker | sort -hr
BASH

输出:

181G    /var/lib/docker
147G    /var/lib/docker/overlay2
26G     /var/lib/docker/containers
5.8G    /var/lib/docker/buildkit
1.2G    /var/lib/docker/image
TEXT

重点已经很清楚:

  • /var/lib/docker/overlay2 占用 147G
  • /var/lib/docker/containers 占用 26G
  • BuildKit cache 也有 5.8G

这不是单点文件膨胀,而是 Docker 存储整体失控。


4. 第一条错误路径:直接 prune

很多人第一反应是:

docker system prune -af
BASH

这次执行后只释放了不到 2G:

Deleted Images:
untagged: registry.local/infer-preprocess:<none>
deleted: sha256:1e4d...

Total reclaimed space: 1.73GB
TEXT

问题依旧:

df -h /
BASH
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       197G  195G  1.6G 100% /
TEXT

这说明至少存在两类问题:

  1. Docker 认为这些层仍然被引用,所以不会清理;
  2. overlay2 里存在 Docker 元数据已经无法关联的残留目录。

生产环境不要看到 overlay2 大就直接执行:

sudo rm -rf /var/lib/docker/overlay2/*
BASH

这会直接破坏镜像层、容器可写层、merged 目录关系。轻则容器启动失败,重则 Docker 元数据损坏。


5. 排查容器日志是否失控

先查 Docker json 日志:

sudo find /var/lib/docker/containers \
  -name "*-json.log" \
  -type f \
  -exec du -h {} \; | sort -hr | head -20
BASH

输出:

14G /var/lib/docker/containers/2f8c.../2f8c...-json.log
8.7G /var/lib/docker/containers/a91d.../a91d...-json.log
2.9G /var/lib/docker/containers/74be.../74be...-json.log
1.3G /var/lib/docker/containers/bbe2.../bbe2...-json.log
TEXT

定位对应容器:

docker ps -a --no-trunc | grep 2f8c
BASH

输出:

2f8c6d7a... registry.local/triton:23.10 tritonserver ... triton-server
TEXT

查看日志内容:

sudo tail -n 20 /var/lib/docker/containers/2f8c*/2f8c*-json.log
BASH

发现大量 TensorRT verbose 日志:

{"log":"[TRT] [V] Layer Conv_317 input dimensions: ...\n","time":"2026-05-15T03:10:21.713912831Z"}
{"log":"[TRT] [V] Tactic 7 time: 0.034ms\n","time":"2026-05-15T03:10:21.714018377Z"}
JSON

根因之一确认:

容器使用 Docker 默认 json-file 日志驱动,但没有配置日志轮转,推理服务 verbose 日志持续刷盘。

临时截断日志:

sudo truncate -s 0 /var/lib/docker/containers/2f8c*/2f8c*-json.log
sudo truncate -s 0 /var/lib/docker/containers/a91d*/a91d*-json.log
BASH

再次查看:

df -h /
BASH

输出:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       197G  171G   27G  87% /
TEXT

第一阶段回收 26G,系统从完全不可写恢复到可操作状态。


6. 排查 deleted 文件句柄

磁盘满时还有一个经典陷阱:

文件已经被删除,但进程仍然持有文件句柄,空间不会释放。

检查:

sudo lsof +L1
BASH

输出:

COMMAND     PID USER   FD   TYPE DEVICE  SIZE/OFF NLINK NODE NAME
python3   18421 root    7w   REG  8,1  11891384320     0 917351 /var/log/infer/postprocess.log (deleted)
tritonser 19277 root   12w   REG  8,1   6979321856     0 917482 /tmp/triton_verbose.log (deleted)
TEXT

两个被删除但仍占用空间的文件,加起来约 18G。

对 Python 服务先尝试 HUP:

sudo kill -HUP 18421
BASH

无效。

这个服务没有实现日志 reopen,只能重启对应容器:

docker restart infer-postprocess
docker restart triton-server
BASH

再次确认:

sudo lsof +L1 | head
df -h /
BASH

输出:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       197G  153G   45G  78% /
TEXT

第二阶段释放 18G。


7. 深挖 overlay2 为什么还有 147G

日志和 deleted FD 清掉后,根分区仍然使用 78%。继续看 overlay2:

sudo du -xhd1 /var/lib/docker/overlay2 | sort -hr | head -30
BASH

输出:

147G /var/lib/docker/overlay2
18G  /var/lib/docker/overlay2/8f2a4c...
15G  /var/lib/docker/overlay2/3c91d2...
13G  /var/lib/docker/overlay2/d91ab7...
11G  /var/lib/docker/overlay2/f73aa2...
TEXT

检查 Docker 视角的占用:

docker system df -v
BASH

输出节选:

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          18        9         42.1GB    16.7GB (39%)
Containers      12        8         21.4GB    2.1GB (9%)
Local Volumes   7         5         18.8GB    3.2GB (17%)
Build Cache     76        0         5.8GB     5.8GB
TEXT

Docker 认为自身主要占用:

  • Images 42.1G
  • Containers 21.4G
  • Volumes 18.8G
  • Build Cache 5.8G

合计不到 90G。

/var/lib/docker 实际还有 153G。这里存在约 60G 差异。

这类差异通常来自:

  • overlay2 孤儿目录;
  • 容器上层写入过大;
  • BuildKit 或中断构建残留;
  • Docker 元数据损坏;
  • 仍有进程挂载 merged 目录。

8. 找出最大的 upperdir

容器的可写层通常在 overlay2 的 diff 目录。

先找最大的 diff

sudo find /var/lib/docker/overlay2 -maxdepth 2 -type d -name diff \
  -exec du -sh {} \; | sort -hr | head -20
BASH

输出:

18G /var/lib/docker/overlay2/8f2a4c.../diff
15G /var/lib/docker/overlay2/3c91d2.../diff
13G /var/lib/docker/overlay2/d91ab7.../diff
TEXT

看其中一个目录:

sudo du -xhd2 /var/lib/docker/overlay2/8f2a4c*/diff | sort -hr | head
BASH

输出:

18G /var/lib/docker/overlay2/8f2a4c.../diff
17G /var/lib/docker/overlay2/8f2a4c.../diff/root/.cache
16G /var/lib/docker/overlay2/8f2a4c.../diff/root/.cache/huggingface
TEXT

这说明某个容器把 HuggingFace 模型缓存写进了容器层,而不是 volume 或宿主机目录。

继续找这个 layer 属于哪个容器:

docker inspect $(docker ps -aq) \
  --format '{{.Name}} {{.GraphDriver.Data.UpperDir}}' | grep '8f2a4c'
BASH

输出:

/model-warmup /var/lib/docker/overlay2/8f2a4c.../diff
TEXT

容器 model-warmup 的可写层写了 18G。

确认容器内路径:

docker exec model-warmup du -sh /root/.cache/huggingface
BASH

输出:

17G /root/.cache/huggingface
TEXT

这个问题不是 Docker bug,是部署方式错误。

模型缓存不应该写进容器层。


9. 处理容器层膨胀

先把缓存迁出来:

mkdir -p /data/model-cache/huggingface

docker cp model-warmup:/root/.cache/huggingface /data/model-cache/
BASH

修改 compose:

services:
  model-warmup:
    image: registry.local/model-warmup:2026-05-15
    volumes:
      - /data/model-cache/huggingface:/root/.cache/huggingface
      - /data/models:/models
    environment:
      HF_HOME: /root/.cache/huggingface
YAML

重建容器:

docker compose up -d --force-recreate model-warmup
BASH

删除旧容器后再清理:

docker rm $(docker ps -aq -f status=exited)
docker system prune -f
BASH

释放后:

df -h /
BASH

输出:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       197G  132G   65G  68% /
TEXT

10. 清理 BuildKit 缓存

BuildKit 缓存虽然不是最大头,但这类服务器经常反复构建 TensorRT 镜像,不清理迟早会变成问题。

查看:

docker builder du
BASH

输出:

ID                                RECLAIMABLE     SIZE
wz0k...                           true            2.1GB
d7n1...                           true            1.8GB
p9aa...                           true            1.4GB
TEXT

清理:

docker builder prune -af
BASH

输出:

Total reclaimed space: 5.76GB
TEXT

注意,不建议把这条命令简单丢到每天凌晨执行。CI 服务器可以清,但推理服务器上如果构建缓存用于加速紧急回滚镜像,清掉会增加恢复时间。


11. 排查 overlay2 孤儿层

这一步最容易误删。

先列出 Docker 当前知道的 UpperDir、LowerDir、WorkDir、MergedDir:

docker inspect $(docker ps -aq) \
  --format '{{.Name}}
Upper={{.GraphDriver.Data.UpperDir}}
Work={{.GraphDriver.Data.WorkDir}}
Merged={{.GraphDriver.Data.MergedDir}}
Lower={{.GraphDriver.Data.LowerDir}}
' > /tmp/docker-layer-used.txt
BASH

列出 overlay2 实际目录:

sudo find /var/lib/docker/overlay2 -maxdepth 1 -mindepth 1 -type d \
  -printf '%f\n' | sort > /tmp/overlay2-all.txt
BASH

提取正在被容器引用的目录 ID:

grep -oE '/var/lib/docker/overlay2/[^/:]+' /tmp/docker-layer-used.txt \
  | awk -F/ '{print $NF}' \
  | sort -u > /tmp/overlay2-used-by-containers.txt
BASH

对比:

comm -23 /tmp/overlay2-all.txt /tmp/overlay2-used-by-containers.txt | head -50
BASH

这只能说明“不被容器直接引用”,不能说明可以删除,因为镜像层也在 overlay2 里。

继续检查 Docker image layerdb:

sudo find /var/lib/docker/image/overlay2/layerdb -type f -name cache-id \
  -exec cat {} \; | sort -u > /tmp/overlay2-used-by-images.txt
BASH

合并引用:

cat /tmp/overlay2-used-by-containers.txt /tmp/overlay2-used-by-images.txt \
  | sort -u > /tmp/overlay2-used.txt
BASH

找疑似孤儿目录:

comm -23 /tmp/overlay2-all.txt /tmp/overlay2-used.txt > /tmp/overlay2-orphan-candidates.txt
BASH

查看候选目录大小:

while read id; do
  sudo du -sh "/var/lib/docker/overlay2/$id" 2>/dev/null
done < /tmp/overlay2-orphan-candidates.txt | sort -hr | head -30
BASH

输出:

12G /var/lib/docker/overlay2/d91ab7...
9.4G /var/lib/docker/overlay2/f73aa2...
6.8G /var/lib/docker/overlay2/aa91c3...
TEXT

删除前,还要确认没有进程挂载它们:

mount | grep '/var/lib/docker/overlay2/d91ab7'
sudo lsof | grep '/var/lib/docker/overlay2/d91ab7'
BASH

如果都没有输出,再记录候选清单:

sudo cp /tmp/overlay2-orphan-candidates.txt /data/backup/overlay2-orphan-candidates-$(date +%F).txt
sudo cp /tmp/docker-layer-used.txt /data/backup/docker-layer-used-$(date +%F).txt
BASH

最终清理前先停止 Docker,避免运行中 layer 变化:

sudo systemctl stop docker
sudo systemctl stop containerd
BASH

删除确认过的孤儿层:

while read id; do
  sudo rm -rf "/var/lib/docker/overlay2/$id"
done < /tmp/overlay2-orphan-candidates.txt
BASH

启动 Docker:

sudo systemctl start containerd
sudo systemctl start docker
BASH

检查:

docker ps
docker system df
df -h /
BASH

结果:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       197G   91G  106G  47% /
TEXT

至此,空间恢复到安全水位。


12. 最终恢复结果

指标 修复前 修复后
根分区使用率 100% 47%
/var/lib/docker/overlay2 147G 64G
/var/lib/docker/containers 26G 740M
BuildKit Cache 5.8G 120M
inode 使用率 100% 34%
docker ps 响应时间 12s ~ 30s < 1s
SSH 登录耗时 20s+ 正常
Triton 502 高频出现 消失

业务侧 P95 延迟也恢复正常:

指标 修复前 修复后
推理接口 P50 42ms 39ms
推理接口 P95 980ms 71ms
推理接口 P99 3.8s 142ms
502 比例 2.7% 0%

延迟暴涨不是模型变慢,而是容器、日志、文件系统写入失败导致服务抖动。


13. 根因总结

这次事故不是单一原因。

根因链路如下:

flowchart TD
    A[TensorRT verbose 日志持续输出] --> B[Docker json-file 日志无限增长]
    C[HuggingFace 缓存写入容器层] --> D[overlay2 upperdir 膨胀]
    E[BuildKit 构建中断] --> F[overlay2 残留层]
    G[日志文件被删除但 FD 未释放] --> H[空间无法回收]
    B --> I[根分区 100%]
    D --> I
    F --> I
    H --> I
    I --> J[dockerd 写 metadata 失败]
    I --> K[journald 写入失败]
    I --> L[容器随机退出]
    L --> M[Nginx upstream 502]

最终结论:

Docker overlay2 撑爆磁盘,本质是日志、缓存、镜像层、容器可写层和构建缓存同时缺少边界控制。


14. 永久修复:配置 Docker 日志轮转

修改 /etc/docker/daemon.json

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}
JSON

重启 Docker:

sudo systemctl restart docker
BASH

验证:

docker info | grep -A5 "Logging Driver"
BASH

如果是新部署环境,建议直接使用 local driver:

{
  "log-driver": "local",
  "log-opts": {
    "max-size": "100m"
  }
}
JSON

local 日志驱动对磁盘占用更友好,也会做压缩。线上长期运行的服务,不建议裸奔使用无限制的 json-file。


15. 永久修复:迁移 Docker data-root

根分区不应该承载 Docker 数据目录。

推荐把 Docker 数据迁到独立数据盘:

sudo systemctl stop docker
sudo systemctl stop containerd

sudo mkdir -p /data/docker
sudo rsync -aHAX --numeric-ids /var/lib/docker/ /data/docker/
BASH

修改 /etc/docker/daemon.json

{
  "data-root": "/data/docker",
  "log-driver": "local",
  "log-opts": {
    "max-size": "100m"
  }
}
JSON

启动:

sudo systemctl start containerd
sudo systemctl start docker
BASH

确认:

docker info | grep "Docker Root Dir"
BASH

输出应为:

Docker Root Dir: /data/docker
TEXT

确认服务正常后,再清理旧目录:

sudo mv /var/lib/docker /var/lib/docker.bak.$(date +%F)
BASH

观察一周没有问题后再删除:

sudo rm -rf /var/lib/docker.bak.2026-05-15
BASH

不要迁移后立刻删旧目录。出问题时还能回滚。


16. 永久修复:模型缓存不要写入容器层

AI 推理环境尤其容易踩这个坑。

这些目录不应该留在容器可写层:

/root/.cache
/root/.cache/huggingface
/root/.cache/torch
/tmp/triton
/tmp/tensorrt
/workspace/build
TEXT

推荐目录结构:

/data
├── docker
├── models
├── engines
├── model-cache
│   ├── huggingface
│   ├── torch
│   └── tensorrt
├── logs
└── datasets
TEXT

Compose 示例:

services:
  triton-server:
    image: registry.local/triton:23.10
    runtime: nvidia
    volumes:
      - /data/models:/models:ro
      - /data/engines:/engines
      - /data/model-cache:/root/.cache
      - /data/logs/triton:/logs
    environment:
      NVIDIA_VISIBLE_DEVICES: all
      HF_HOME: /root/.cache/huggingface
    command:
      - tritonserver
      - --model-repository=/models
      - --log-verbose=0
YAML

重点是:

镜像只放程序,模型和缓存放宿主机数据盘,日志单独管理。


17. 巡检脚本

下面这个脚本用于检查:

  • 根分区使用率
  • inode 使用率
  • Docker 日志大文件
  • deleted 文件句柄
  • overlay2 大目录
  • BuildKit cache

保存为:

/usr/local/bin/docker-storage-check.sh
BASH

内容:

#!/usr/bin/env bash
set -euo pipefail

ROOT_THRESHOLD=80
INODE_THRESHOLD=80
LOG_THRESHOLD="+1G"

echo "===== filesystem usage ====="
df -h /

echo
echo "===== inode usage ====="
df -i /

root_usage=$(df / | awk 'NR==2 {gsub("%","",$5); print $5}')
inode_usage=$(df -i / | awk 'NR==2 {gsub("%","",$5); print $5}')

if [ "$root_usage" -ge "$ROOT_THRESHOLD" ]; then
  echo "WARN: root filesystem usage is ${root_usage}%"
fi

if [ "$inode_usage" -ge "$INODE_THRESHOLD" ]; then
  echo "WARN: root inode usage is ${inode_usage}%"
fi

echo
echo "===== docker system df ====="
docker system df || true

echo
echo "===== large docker json logs ====="
sudo find /var/lib/docker/containers \
  -name "*-json.log" \
  -type f \
  -size "$LOG_THRESHOLD" \
  -exec du -h {} \; 2>/dev/null | sort -hr || true

echo
echo "===== deleted files still held by processes ====="
sudo lsof +L1 2>/dev/null | awk 'NR==1 || $7 > 1073741824 {print}' || true

echo
echo "===== largest overlay2 diff dirs ====="
sudo find /var/lib/docker/overlay2 \
  -maxdepth 2 \
  -type d \
  -name diff \
  -exec du -sh {} \; 2>/dev/null | sort -hr | head -20 || true
BASH

加执行权限:

sudo chmod +x /usr/local/bin/docker-storage-check.sh
BASH

配置 cron:

sudo crontab -e
BASH

加入:

*/15 * * * * /usr/local/bin/docker-storage-check.sh >> /var/log/docker-storage-check.log 2>&1
CRON

18. 回滚方案

修复 overlay2 这类问题一定要有回滚路径。

18.1 日志截断回滚

truncate 日志不可逆,但不会影响容器运行。最多损失历史日志。

18.2 Docker data-root 迁移回滚

如果迁移后 Docker 异常:

sudo systemctl stop docker
sudo systemctl stop containerd
BASH

恢复 /etc/docker/daemon.json 中的 data-root

{
  "data-root": "/var/lib/docker"
}
JSON

如果旧目录还在:

sudo mv /var/lib/docker.bak.2026-05-15 /var/lib/docker
BASH

启动:

sudo systemctl start containerd
sudo systemctl start docker
BASH

18.3 overlay2 孤儿层删除回滚

这一步最麻烦。

删除前至少保留:

/tmp/overlay2-all.txt
/tmp/overlay2-used.txt
/tmp/overlay2-orphan-candidates.txt
/tmp/docker-layer-used.txt
TEXT

如果删除后容器异常,优先重新拉镜像和重建容器,不建议手工拼回 overlay2。

docker compose pull
docker compose up -d --force-recreate
BASH

overlay2 不是业务数据目录,不应该依赖它恢复业务数据。


19. 不建议做的事

19.1 不要直接删除 overlay2

错误示例:

sudo rm -rf /var/lib/docker/overlay2/*
BASH

这基本等于破坏 Docker 存储。

19.2 不要盲目定时 prune

错误示例:

0 3 * * * docker system prune -af
CRON

这会带来几个问题:

  • 清掉构建缓存,CI 变慢;
  • 清掉预拉取镜像,回滚变慢;
  • 误删未使用但即将切换的镜像;
  • 推理服务冷启动时间变长。

19.3 不要把模型下载到容器层

错误示例:

RUN python download_model.py
DOCKERFILE

如果模型很大,镜像会膨胀;如果运行时再下载,容器层会膨胀。更好的做法是模型仓库独立挂载。


20. 推荐监控项

Prometheus 建议至少加这些指标:

node_filesystem_avail_bytes
node_filesystem_size_bytes
node_filesystem_files_free
node_filesystem_files
node_filesystem_readonly
TEXT

Docker 侧建议采集:

/var/lib/docker/overlay2 size
/var/lib/docker/containers size
large json log count
deleted fd size
docker system df
TEXT

告警阈值:

指标 Warning Critical
根分区使用率 75% 85%
inode 使用率 70% 85%
单个 json log 1G 5G
overlay2 总量 70% of disk 85% of disk
deleted FD 占用 2G 10G

21. 架构调整前后对比

事故前:

flowchart LR
    A[Triton 容器] --> B[/var/lib/docker/overlay2]
    C[Python 服务日志] --> D[/var/lib/docker/containers]
    E[模型缓存] --> B
    F[BuildKit Cache] --> G[/var/lib/docker/buildkit]
    B --> H[根分区]
    D --> H
    G --> H

问题是所有东西都压在根分区上。

调整后:

flowchart LR
    A[Triton 容器] --> B[/data/models]
    A --> C[/data/engines]
    A --> D[/data/logs]
    A --> E[/data/model-cache]
    F[Docker data-root] --> G[/data/docker]
    H[根分区] --> I[系统文件]

根分区只承载系统文件,Docker、模型、日志、缓存全部进入数据盘。


22. 配图建议

文章配图可以放在:

/source/img/docker-overlay2-disk-full/
TEXT

建议准备三张图:

cover.png
overlay2-structure.png
docker-storage-after.png
TEXT

22.1 cover.png

内容:

Docker overlay2 -> root filesystem 100% -> containers crash
TEXT

22.2 overlay2-structure.png

内容:

lowerdir + upperdir + workdir -> merged
TEXT

22.3 docker-storage-after.png

内容:

/data/docker
/data/models
/data/logs
/data/model-cache
TEXT

这三张图足够,不需要堆太多示意图。


23. 结论

这次故障的核心不是“Docker 占用大”,而是 Docker 存储没有边界。

最终处理顺序是:

先恢复可写空间
再处理日志
再处理 deleted FD
再定位容器可写层
再清 BuildKit
最后谨慎处理 overlay2 孤儿层
TEXT

长期方案也很明确:

  • Docker data-root 不放根分区;
  • Docker 日志必须限制大小;
  • 模型、缓存、日志必须挂载到数据盘;
  • 不要把 HuggingFace、TensorRT、Torch cache 写进容器层;
  • overlay2 清理必须先判断引用关系;
  • 磁盘和 inode 必须进入监控。

生产环境里,磁盘打满不是小问题。它会让 Docker、journald、systemd、SSH、业务容器一起退化。等到 Use% 变成 100% 再处理,通常已经晚了。


Nickname
Email
Website
0/500
  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • 😂
  • 😀
  • 😅
  • 😊
  • 🙂
  • 🙃
  • 😌
  • 😍
  • 😘
  • 😜
  • 😝
  • 😏
  • 😒
  • 🙄
  • 😳
  • 😡
  • 😔
  • 😫
  • 😱
  • 😭
  • 💩
  • 👻
  • 🙌
  • 🖕
  • 👍
  • 👫
  • 👬
  • 👭
  • 🌚
  • 🌝
  • 🙈
  • 💊
  • 😶
  • 🙏
  • 🍦
  • 🍉
  • 😣
  • 颜文字
  • Emoji
  • Bilibili
0 comments
No comment