← กลับ
DockerLinuxDiskTroubleshooting

Docker ใช้พื้นที่พุ่งผิดปกติ ตรวจยังไงให้เจอตัวการ

df บอก /var/lib/docker เต็ม 80GB — แต่ตรวจหาตัวการ container/image/volume/build cache ไหนกินเยอะที่สุด ก่อนตัดสินใจลบ

2025-11-05อ่าน 5 นาทีใหม่

สถานการณ์

$ df -h /var/lib/docker
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       100G   95G  5.0G  95% /

Disk เต็ม — แต่ลบอะไรดีโดยไม่ลบของที่ใช้อยู่?

อย่ารีบ docker system prune -a --volumes — อาจลบ volume สำคัญหายแน่นอน ต้องดูก่อนว่าตัวการคืออะไร

คำสั่งที่ใช้สำรวจ

ภาพรวม

docker system df

ผลลัพธ์:

TYPE            TOTAL   ACTIVE  SIZE      RECLAIMABLE
Images          45      12      28.4GB    18.2GB (64%)
Containers      18      6       1.5GB     0.8GB (53%)
Local Volumes   12      8       42.1GB    8.3GB (19%)
Build Cache     156     0       12.5GB    12.5GB (100%)

อ่าน:

  • TOTAL = ทั้งหมด
  • ACTIVE = ที่ใช้อยู่
  • SIZE = ขนาดรวม
  • RECLAIMABLE = ที่ลบได้ทันทีโดยไม่กระทบ

ตัวอย่างนี้ — Build Cache 12.5GB ลบได้ทั้งหมด

Verbose ดูแต่ละตัว

docker system df -v

จะแสดง:

  • Images แต่ละตัว ขนาด ใช้อยู่มั้ย
  • Containers แต่ละตัว disk ที่ใช้
  • Volumes แต่ละตัว ขนาด ใช้อยู่มั้ย

เจาะดูแต่ละประเภท

1. Images

docker images
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" \
  | sort -k 3 -h

หา image ที่ใหญ่ที่สุด:

docker images --format "{{.Size}}\t{{.Repository}}:{{.Tag}}" | sort -hr | head

ลบ image เก่า / dangling:

# Dangling = ไม่มี tag (build เสร็จแต่ tag ใหม่ทับแล้ว)
docker image prune

# ลบ image ที่ไม่มี container ใช้
docker image prune -a

# ลบ image เก่ากว่า 7 วัน
docker image prune -a --filter "until=168h"

2. Containers

ดู disk ที่ container แต่ละตัวกิน:

docker ps -as

ผลลัพธ์:

CONTAINER ID  IMAGE         SIZE
abc123        myapp:1.0     6GB (virtual 800MB)   ← เขียนไฟล์ใน container
def456        postgres:16   180kB (virtual 350MB)

SIZE = layer ใหม่ที่ container เพิ่ม (RW layer) virtual = ขนาด image base + layer ใหม่

ถ้า container เก็บข้อมูลในตัว (ไม่ใช่ใน volume) — RW layer จะใหญ่ขึ้นเรื่อยๆ

แก้: เก็บข้อมูลใน volume แทน

3. Container Logs

ส่วนที่ทุกคนลืม — log ของ container กิน disk เยอะที่สุด:

sudo du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null \
  | sort -hr | head -10

อ่านเพิ่ม: Docker Log เต็ม Disk

4. Volumes

docker volume ls
docker volume ls -q -f dangling=true   # volume ที่ไม่มี container ใช้

ดูขนาด volume:

sudo du -sh /var/lib/docker/volumes/*/ | sort -hr | head

ลบ dangling volume (อันที่ไม่มี container):

docker volume prune

⚠️ ระวัง: ตรวจให้ดีก่อนลบ! Volume อาจเก็บข้อมูล production ที่ container หยุดชั่วคราว

ดู volume แต่ละตัวเก็บอะไร:

docker volume inspect <volume-name>
sudo ls /var/lib/docker/volumes/<volume-name>/_data/

5. Build Cache (BuildKit)

BuildKit cache สะสมเร็วมาก:

docker buildx du

ดู cache แต่ละ layer ที่เก็บไว้

ลบ:

# ลบ cache ที่ใช้นาน
docker buildx prune --filter "until=168h"

# ลบทั้งหมด
docker buildx prune -a -f

# หรือ
docker builder prune -a -f

6. Overlay2 (storage driver)

/var/lib/docker/overlay2 = layer storage ของ image + container

sudo du -sh /var/lib/docker/overlay2/* | sort -hr | head -10

อย่าลบไฟล์ใน folder นี้ตรงๆ — ใช้ docker prune ให้ Docker จัดการ

ถ้าหลังลบทุกอย่างแล้วยัง orphan — restart docker:

sudo systemctl restart docker

วิธีหาว่าใครคนเขียน Disk

ดู process ที่เขียน I/O มากสุด

sudo iotop -aoP
PID   PRIO  USER  DISK READ  DISK WRITE  COMMAND
1234  be/4  root  0 B          5.2 MB     dockerd
5678  be/4  root  0 B          3.8 MB     containerd

หรือใช้ pidstat:

sudo pidstat -d 5

ดู file ที่ใหญ่และเปลี่ยนล่าสุด

sudo find /var/lib/docker -size +100M -mtime -7 -exec ls -lh {} \; \
  | sort -k 5 -h

หาไฟล์ใหญ่กว่า 100MB ที่ถูกแก้ใน 7 วันล่าสุด

Investigative Workflow

df -h เห็น disk เต็ม
  ↓
docker system df ดูภาพรวม
  ↓
หาตัวที่ RECLAIMABLE สูงสุด
  │
  ├─ Build Cache มากสุด → docker buildx prune -a
  │
  ├─ Images มากสุด → docker images --format ดู เลือกลบ tag เก่า
  │
  ├─ Containers มากสุด → ดู log files หรือ RW layer
  │
  └─ Volumes มากสุด → docker volume ls + ตรวจให้แน่ใจก่อนลบ
       ↓
หลังลบแล้ว df ยัง stuck?
  ↓
sudo systemctl restart docker (orphan cleanup)

ตัวอย่างจริง: pipeline สะสม cache

CI runner รัน Docker build ทุก commit เก็บไว้ 6 เดือน:

$ docker system df
TYPE          TOTAL   SIZE       RECLAIMABLE
Build Cache   2,847   62.3GB     62.3GB (100%)

แก้:

docker buildx prune -a -f
# ได้พื้นที่คืน 62GB

ป้องกัน — ตั้ง garbage collection ใน BuildKit:

/etc/docker/daemon.json:

{
  "builder": {
    "gc": {
      "enabled": true,
      "defaultKeepStorage": "20GB",
      "policy": [
        {
          "keepDuration": "168h",
          "filter": ["type==source.local", "type==exec.cachemount"]
        },
        {
          "keepDuration": "168h",
          "filter": ["type==regular"]
        }
      ]
    }
  }
}

คำสั่งสรุป — disk เต็มแล้วทำอะไร

# 1. ดูภาพรวม
docker system df

# 2. ดู verbose
docker system df -v

# 3. ตรวจ container log
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -hr | head

# 4. ลบที่ปลอดภัย (ไม่กระทบ container ที่รัน)
docker container prune -f          # ลบ stopped container
docker image prune -a -f           # ลบ image ที่ไม่ใช้
docker volume prune -f             # dangling volume
docker buildx prune -a -f          # build cache

# 5. หรือทำพร้อมกัน (ระวัง --volumes!)
docker system prune -a -f          # ไม่รวม volume — ปลอดภัย
docker system prune -a --volumes -f  # รวม volume — ระวัง

# 6. ถ้ายังเต็ม
sudo systemctl restart docker

ป้องกันไม่ให้กลับมาเต็มอีก

  1. ตั้ง log limit ใน daemon.json
  2. ตั้ง BuildKit GC policy
  3. ตั้ง cron clean ทุกอาทิตย์:
    0 3 * * 0 docker system prune -af --filter "until=336h" >> /var/log/docker-prune.log 2>&1
    
  4. ใช้ named volume สำหรับ data — ไม่ให้ container RW layer โต
  5. Multi-stage build ลด image size
  6. ตั้ง Prometheus alert เมื่อ disk > 80%

สรุป

Disk เต็มไม่ใช่ "เหตุการณ์ฉุกเฉิน" — เป็นสัญญาณว่า cleanup policy ไม่ได้ตั้งไว้

ตรวจตามลำดับ: docker system df → ดู type ที่ใหญ่ที่สุด → ลบเฉพาะที่ปลอดภัย → ตั้ง automation ป้องกันครั้งหน้า

อ่านต่อ: Docker Log เต็ม Disk — case ย่อยที่เจอบ่อยสุด

← ดูบทความอื่น