← กลับ
DockerTroubleshootingLinuxDisk

Docker Log เต็ม Disk แต่ลบแล้วทำไมพื้นที่ไม่คืน

ลบ container, prune image แล้ว df ยังเต็ม — เพราะ container ยังเปิดไฟล์ log อยู่ วิธีจัดการให้พื้นที่คืนจริงและไม่กลับมาเต็มอีก

2025-10-15อ่าน 4 นาทีใหม่

อาการ

df -h บอก /var/lib/docker กิน 80GB เต็ม disk

$ docker system prune -a --volumes -f
Total reclaimed space: 0B

อ้าว ทำไมไม่คืน?

$ sudo du -sh /var/lib/docker/containers/*/
2.3G    /var/lib/docker/containers/abc123.../
14G     /var/lib/docker/containers/def456.../
8G      /var/lib/docker/containers/ghi789.../

ปัญหาเกือบทั้งหมดมาจาก container log file ที่ใหญ่มาก

ทำไมไม่คืน

Docker default log driver คือ json-file — log ทุก stdout/stderr ของ container ลง:

/var/lib/docker/containers/<id>/<id>-json.log

ไฟล์นี้ โตได้ไม่จำกัด ถ้าไม่ตั้ง limit

ที่สำคัญ — ถ้า container ยัง running, process ยังเปิด file handle อยู่ ถ้าลบไฟล์ด้วย rm พื้นที่จะไม่คืนจนกว่า process จะปิด file (Linux behavior ทั่วไป)

วิธีแก้

Step 1: หา container ที่ log ใหญ่ที่สุด

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

ผลลัพธ์:

12G  /var/lib/docker/containers/def456abc/def456abc-json.log
8.3G /var/lib/docker/containers/ghi789def/ghi789def-json.log

Step 2: หา container name จาก ID

docker inspect --format='{{.Name}}' def456abc
# /noisy-app

Step 3: Truncate log โดย container ยังรันอยู่

ถ้า container กำลังรัน — อย่า rm ไฟล์ ใช้ truncate แทน:

# truncate ไฟล์ให้ขนาด 0 — process ที่เปิด file อยู่ใช้ต่อได้
sudo truncate -s 0 /var/lib/docker/containers/def456abc/def456abc-json.log

> แทนก็ได้:

sudo sh -c 'echo > /var/lib/docker/containers/def456abc/def456abc-json.log'

ทันทีที่ truncate — df -h จะเห็นพื้นที่คืน

Step 4: ถ้ารู้ว่าจะลบทั้ง container

docker rm -f noisy-app
docker system prune -f

ทำไม rm ตรงๆ ไม่ดี

ถ้าใช้ rm /var/lib/docker/containers/*/*-json.log:

  • Container ยังรัน → file handle ยังเปิด → space ไม่คืน (deleted but inode in use)
  • ตรวจด้วย lsof | grep deleted:
    sudo lsof | grep deleted | head
    # docker  1234  ...  deleted   /var/lib/docker/containers/.../json.log
    

ต้อง restart container ถึงจะคืน — กระทบ service

ใช้ truncate ดีกว่า — file size = 0 ทันที process ยังเปิดต่อได้ไม่งง

ป้องกันไม่ให้เกิดอีก

วิธีที่ 1: ตั้ง log limit ใน Docker daemon (แนะนำ)

/etc/docker/daemon.json:

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

restart docker:

sudo systemctl restart docker

ตั้งแบบนี้ — ทุก container ใหม่จะมี log สูงสุด 50MB × 3 = 150MB

สำคัญ: config นี้ใช้กับ container ใหม่ เท่านั้น — container ที่รันอยู่แล้วยังใช้ config เดิม ต้อง restart container ถึง apply

วิธีที่ 2: ตั้ง per-container ใน compose

services:
  app:
    image: myapp
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"

วิธีที่ 3: เปลี่ยนเป็น log driver อื่น

ถ้า log เยอะมาก — ส่งออกไปเก็บข้างนอก ใช้ centralized logging แทน:

{
  "log-driver": "loki",
  "log-opts": {
    "loki-url": "http://loki.internal:3100/loki/api/v1/push",
    "loki-batch-size": "400"
  }
}

ดู Centralized Logging ด้วย Loki สำหรับ stack ที่ต้องตั้งฝั่ง receiver

หา space ที่หายไปด้วย ncdu

sudo apt install ncdu
sudo ncdu /var/lib/docker

interactive ลำดับ folder ตามขนาด — กด Enter เพื่อ explore กด d เพื่อลบ

อย่าลืมส่วนอื่นของ Docker

/var/lib/docker มีของอื่นนอกจาก log:

sudo du -sh /var/lib/docker/*

อาจเห็น:

  • containers/ — container data + log
  • image/ — layer ของ image
  • volumes/ — named volume
  • overlay2/ — storage layer ของ container ที่รัน
  • buildkit/ — cache ของ docker build

แต่ละอันมีคำสั่ง prune ของมัน:

docker container prune          # ลบ container ที่หยุด
docker image prune -a           # ลบ image ที่ไม่ใช้
docker volume prune             # ลบ volume ที่ไม่มี container ใช้
docker builder prune            # ลบ build cache

# ทำทุกอย่างพร้อมกัน
docker system prune -a --volumes -f

เช็คลิสต์เวลา disk เต็ม

# 1. ดูว่า /var/lib/docker ใหญ่จริงมั้ย
sudo du -sh /var/lib/docker

# 2. หา container ที่ log ใหญ่สุด
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -hr | head

# 3. truncate log (ระหว่าง container ยังรัน)
sudo truncate -s 0 /var/lib/docker/containers/<id>/<id>-json.log

# 4. หรือ prune ของที่ไม่ใช้
docker system prune -a --volumes -f

# 5. ตั้ง daemon config ป้องกัน
sudo nano /etc/docker/daemon.json
sudo systemctl restart docker

# 6. restart container ที่อยู่ก่อนตั้ง config
docker compose down && docker compose up -d

สรุป

ถ้าเจอ Docker disk เต็ม — 80% เกิดจาก log ใหญ่

วิธีแก้:

  • เร็ว: truncate -s 0 ที่ไฟล์ json.log
  • ถาวร: ตั้ง max-size + max-file ใน daemon config

ตั้ง config ที่ถูกตั้งแต่ install Docker ครั้งแรก ก็จะไม่กลับมาเจอเหตุการณ์นี้อีก

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