สถานการณ์
$ 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
ป้องกันไม่ให้กลับมาเต็มอีก
- ตั้ง log limit ใน daemon.json
- ตั้ง BuildKit GC policy
- ตั้ง cron clean ทุกอาทิตย์:
0 3 * * 0 docker system prune -af --filter "until=336h" >> /var/log/docker-prune.log 2>&1 - ใช้ named volume สำหรับ data — ไม่ให้ container RW layer โต
- Multi-stage build ลด image size
- ตั้ง Prometheus alert เมื่อ disk > 80%
สรุป
Disk เต็มไม่ใช่ "เหตุการณ์ฉุกเฉิน" — เป็นสัญญาณว่า cleanup policy ไม่ได้ตั้งไว้
ตรวจตามลำดับ: docker system df → ดู type ที่ใหญ่ที่สุด → ลบเฉพาะที่ปลอดภัย → ตั้ง automation ป้องกันครั้งหน้า
อ่านต่อ: Docker Log เต็ม Disk — case ย่อยที่เจอบ่อยสุด