ลดความยุ่งยากในการใช้คลาวด์ พูดคุยกับเจ้าหน้าที่

Home คืนพื้นที่ดิสก์ที่ Docker ใช้ด้วย docker system prune

คืนพื้นที่ดิสก์ที่ Docker ใช้ด้วย docker system prune

เซิร์ฟเวอร์ที่ใช้ Docker มาสักระยะมักมีพื้นที่ดิสก์ลดลงเรื่อย ๆ โดยไม่รู้ตัว เพราะทุกครั้งที่ดึง Image เวอร์ชันใหม่ Image เก่ายังค้างอยู่ Container ที่หยุดแล้วไม่ถูกลบ และการ Build Image สร้าง Cache สะสมไว้ใน /var/lib/docker สุดท้ายดิสก์เต็มจนฐานข้อมูลเขียนไม่ได้หรือบริการล่ม

Docker มีคำสั่งตระกูล prune สำหรับลบของที่ไม่ได้ใช้แล้ว บทความนี้อธิบายวิธีดูว่าพื้นที่หายไปกับอะไร คำสั่งแต่ละตัวลบอะไรบ้าง ตัวไหนปลอดภัย ตัวไหนเสี่ยงทำข้อมูลหาย และวิธีตั้งให้ทำความสะอาดอัตโนมัติ

สิ่งที่ต้องเตรียม

  • Linux Server ที่ใช้ Docker Engine รุ่นปัจจุบัน (23.0 ขึ้นไป) ตรวจด้วย docker version
  • สิทธิ์ sudo หรือผู้ใช้ในกลุ่ม docker
  • ไฟล์สำรองของ Volume ที่มีข้อมูลสำคัญ ก่อนใช้คำสั่งใดที่เกี่ยวกับ Volume ดู สำรองและกู้คืนข้อมูล Docker Volume

ขั้นตอนที่ 1: ดูว่าพื้นที่ถูกใช้ไปกับอะไร

เริ่มจากภาพรวมของทั้งเครื่อง

df -h /var/lib/docker

จากนั้นให้ Docker สรุปการใช้พื้นที่ของตัวเอง

docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          24        5         9.8GB     7.2GB (73%)
Containers      9         5         310MB     120MB (38%)
Local Volumes   7         4         3.1GB     900MB (29%)
Build Cache     63        0         2.4GB     2.4GB

คอลัมน์ RECLAIMABLE คือพื้นที่ที่คืนได้เพราะไม่มี Container ที่ทำงานอยู่ใช้งาน ตัวอย่างนี้ Image กินพื้นที่มากที่สุด ถ้าต้องการรายละเอียดทีละรายการ เช่น Volume ใดใหญ่และยังมี Container ผูกอยู่หรือไม่ ใช้

docker system df -v

ถ้า docker system df รวมแล้วน้อยกว่าที่ df -h แสดงมาก ให้ตรวจไฟล์ Log ของ Container ซึ่งไม่ได้นับรวมในตารางนี้

sudo sh -c 'du -h /var/lib/docker/containers/*/*-json.log' | sort -h | tail

ถ้าไฟล์ Log ใหญ่เป็น GB แก้ต้นเหตุตาม จำกัดขนาด Log ของ Docker Container เพราะ prune ไม่ลบ Log ของ Container ที่ยังอยู่

ขั้นตอนที่ 2: รู้จักคำสั่ง prune แต่ละตัว

คำสั่งลบอะไรความเสี่ยง
docker container pruneContainer ที่หยุดแล้วทั้งหมดต่ำ แต่ไฟล์ที่เขียนใน Container นั้น (นอก Volume) จะหาย
docker image pruneImage แบบ dangling (ไม่มี TAG แสดงเป็น <none>)ต่ำมาก
docker image prune -aImage ทุกตัวที่ไม่มี Container ใช้ รวมตัวที่มี TAGต่ำ แต่ครั้งหน้าต้องดาวน์โหลดใหม่
docker builder pruneBuild Cacheต่ำ Build ครั้งหน้าช้าลง
docker network pruneNetwork ที่ไม่มี Container ใช้ต่ำ
docker volume pruneAnonymous Volume ที่ไม่มี Container ใช้สูง ข้อมูลหายถาวร
docker volume prune -aVolume ทุกตัวที่ไม่มี Container ใช้ รวม Named Volumeสูงมาก

ตั้งแต่ Docker Engine 23.0 เป็นต้นมา docker volume prune ลบเฉพาะ Anonymous Volume เป็นค่าเริ่มต้น ต้องใส่ -a จึงจะลบ Named Volume ด้วย บทความเก่าบนอินเทอร์เน็ตที่เขียนก่อนหน้านั้นอาจอธิบายต่างจากนี้

หมายเหตุ: คำว่า "ไม่มี Container ใช้" รวมถึงกรณีที่คุณเพิ่งสั่ง docker compose down ไป Volume ฐานข้อมูลของโปรเจกต์ที่ปิดชั่วคราวจะถูกมองว่าไม่ได้ใช้และถูกลบได้ ห้ามใช้ volume prune -a บนเครื่องจริงโดยไม่ตรวจรายการก่อนเด็ดขาด

ขั้นตอนที่ 3: ใช้ docker system prune

docker system prune รวมหลายคำสั่งไว้ในคำสั่งเดียว ค่าเริ่มต้นจะลบ Container ที่หยุดแล้ว, Network ที่ไม่ได้ใช้, Image แบบ dangling และ Build Cache ที่ไม่ได้อ้างอิง ระบบจะแสดงรายการและถามยืนยันก่อนเสมอ

docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - unused build cache

Are you sure you want to continue? [y/N]

ถ้อยคำของรายการอาจต่างกันเล็กน้อยตามเวอร์ชันของ Docker (บางรุ่นเขียนว่า all dangling build cache) อ่านรายการให้ครบก่อนพิมพ์ y เมื่อเสร็จจะแสดงบรรทัด Total reclaimed space: ...

ถ้าต้องการคืนพื้นที่มากขึ้น เพิ่ม -a เพื่อลบ Image ทุกตัวที่ไม่มี Container ใช้

docker system prune -a

ทั้งสองแบบ ไม่ลบ Volume เว้นแต่จะใส่ --volumes เพิ่ม ซึ่งไม่แนะนำให้ใช้ในงานประจำ

ลบเฉพาะของที่เก่ากว่ากำหนด

ตัวเลือก --filter "until=..." ช่วยเก็บของที่เพิ่งสร้างไว้ เช่น Image ที่เพิ่งดึงมาเพื่อเตรียม Deploy

docker image prune -a --filter "until=168h"
docker builder prune --filter "until=72h"

ตัวอย่างแรกลบ Image ที่ไม่ได้ใช้และสร้างนานกว่า 7 วัน ตัวอย่างที่สองลบ Build Cache ที่เก่ากว่า 3 วัน

ขั้นตอนที่ 4: ตรวจก่อนลบ Volume

ถ้า Volume กินพื้นที่มากและต้องการลบ ให้ดูรายการที่ไม่มี Container ผูกอยู่ก่อน

docker volume ls -f dangling=true

ตรวจเนื้อหาของ Volume ที่ไม่แน่ใจ โดยเปิดดูแบบอ่านอย่างเดียว

docker run --rm -v ชื่อvolume:/data:ro debian:bookworm-slim ls -la /data

จากนั้นลบทีละตัวด้วยชื่อ ซึ่งปลอดภัยกว่าการ prune ทั้งหมด

docker volume rm ชื่อvolume

ขั้นตอนที่ 5: ตั้งทำความสะอาดอัตโนมัติ

สำหรับเครื่องที่ Deploy บ่อย ตั้ง Cronjob ให้ลบ Image และ Build Cache เก่าทุกสัปดาห์ โดยไม่แตะ Volume

sudo crontab -e
0 3 * * 0 /usr/bin/docker image prune -af --filter "until=168h" >> /var/log/docker-prune.log 2>&1
15 3 * * 0 /usr/bin/docker builder prune -f --filter "until=168h" >> /var/log/docker-prune.log 2>&1

-f ข้ามการถามยืนยัน จึงใช้ใน Cron ได้ ตรวจ path ของคำสั่งด้วย which docker ก่อน เพราะบางระบบติดตั้งไว้คนละที่ พื้นฐานการเขียน Cron ดูได้ที่ วิธีตั้ง Cronjob หรือ Crontab เพื่อให้ Script ทำงานอัตโนมัติบน Linux

ตรวจสอบผลลัพธ์

docker system df
df -h /var/lib/docker

คอลัมน์ RECLAIMABLE ควรลดลงใกล้ 0 สำหรับประเภทที่เพิ่งลบ และ df -h ต้องแสดงพื้นที่ว่างเพิ่มขึ้น จากนั้นตรวจว่าบริการทั้งหมดยังทำงานปกติด้วย docker ps และเปิดเว็บไซต์ทดสอบ

ปัญหาที่พบบ่อย

prune แล้วแต่พื้นที่แทบไม่ลด

พื้นที่ส่วนใหญ่อาจอยู่ที่ Volume ที่ยังใช้งาน ไฟล์ Log ของ Container หรือไฟล์นอก Docker เลย ใช้ docker system df -v ร่วมกับ sudo du -xh --max-depth=1 /var/lib/docker | sort -h และแนวทางใน ดิสก์เต็ม: ตรวจสอบพื้นที่และหาไฟล์ขนาดใหญ่บน Linux

ลบ Image แล้ว Container รีสตาร์ตไม่ขึ้น

prune ไม่ลบ Image ที่ Container ใดใช้อยู่ ไม่ว่าจะทำงานหรือหยุดอยู่ แต่ถ้าลบ Container ที่หยุดไปพร้อมกัน แล้วภายหลังสั่ง docker compose up ระบบจะดึง Image ใหม่เอง ซึ่งต้องออกอินเทอร์เน็ตได้และอาจได้เวอร์ชันใหม่กว่าเดิมหากใช้ TAG latest

ข้อมูลฐานข้อมูลหายหลังสั่ง prune

เกิดจากใช้ --volumes หรือ volume prune -a ขณะโปรเจกต์ถูก down อยู่ Docker ไม่มีถังขยะให้กู้คืน ต้องกู้จากไฟล์สำรองเท่านั้น นี่คือเหตุผลที่ควรสำรอง Volume อย่างสม่ำเสมอ

ดิสก์เต็มจนสั่ง docker ไม่ได้

ถ้าคำสั่ง Docker ค้างหรือ Error เพราะดิสก์เต็ม 100% ให้ลบไฟล์ขนาดใหญ่นอก Docker ที่ปลอดภัย เช่น Log เก่าใน /var/log หรือล้าง Log ของ Container ด้วย truncate ก่อน แล้วค่อยใช้ prune ห้ามลบไฟล์ใน /var/lib/docker ด้วยมือโดยตรง เพราะจะทำให้ Docker เสียหาย

หากพื้นที่ดิสก์ไม่พอกับการใช้งานจริง สามารถขยายดิสก์ของเซิร์ฟเวอร์ได้ ดู การขยายพื้นที่ Partition หลังเพิ่มพื้นที่ Disk Space (Linux) หรือติดต่อทีมงาน THAI DATA CLOUD ได้ที่ https://thaidata.cloud/contact/

ผู้ให้บริการคลาวด์ไทย
เพื่อธุรกิจของคนไทย

"มุ่งมั่น" และ "มั่นคง"
พร้อมรับมือทุกการเติบโต
Trust Cloud
คลาว์ที่ปลอดภัย
คือรากฐานที่มั่นคง
cloud security