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

ตรวจว่า Docker ใช้พื้นที่ดิสก์ไปกับอะไร แล้วลบ Image, Container, Build Cache ที่ไม่ใช้ด้วยคำสั่ง prune อย่างปลอดภัยโดยไม่ทำข้อมูลใน Volume หาย

โดย ทีมงาน THAI DATA CLOUD อัปเดต อ่าน 16 นาที เข้าชม 10 ครั้ง

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

คำตอบสั้น ๆ: ตรวจว่า Docker ใช้พื้นที่ดิสก์ไปกับอะไร แล้วลบ Image, Container, Build Cache ที่ไม่ใช้ด้วยคำสั่ง prune อย่างปลอดภัยโดยไม่ทำข้อมูลใน Volume หาย

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

เซิร์ฟเวอร์ที่ใช้ 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/

ทำความเข้าใจ Docker ก่อนเริ่ม

พื้นที่ดิสก์ที่หายไปบนเครื่องที่รันคอนเทนเนอร์มักไม่ได้มาจากไฟล์ของคุณ แต่มาจากสามแหล่งที่มองไม่เห็นในการดูขนาดโฟลเดอร์ตามปกติ คืออิมเมจรุ่นเก่าที่ยังค้าง ชั้นข้อมูลของสิ่งที่หยุดทำงานไปแล้ว และบันทึกการทำงานที่โตไม่มีเพดาน การล้างจึงต้องรู้ว่ากำลังลบอะไรอยู่ เพราะคำสั่งล้างแบบกวาดทั้งหมดจะลบพื้นที่จัดเก็บที่ไม่มีใครใช้อยู่ไปด้วย ซึ่งอาจเป็นฐานข้อมูลของบริการที่คุณเพิ่งหยุดไว้ชั่วคราว

สิ่งที่ต้องเตรียมก่อนใช้งาน Docker

  • สิทธิ์ผู้ดูแลระบบบนเครื่องนั้น
  • รายการบริการที่ต้องไม่ถูกแตะ พร้อมชื่อพื้นที่จัดเก็บที่แต่ละบริการใช้
  • สำเนาสำรองของข้อมูลสำคัญก่อนล้าง เพราะการลบพื้นที่จัดเก็บย้อนกลับไม่ได้

ตรวจสอบว่า Docker ทำงานถูกต้องแล้ว

  1. ดูรายงานการใช้พื้นที่ก่อนและหลัง แล้วเทียบว่าพื้นที่คืนมาจากส่วนที่ตั้งใจจริง
  2. ตรวจว่าบริการที่ยังต้องทำงานอยู่ยังทำงานปกติหลังล้าง
  3. ตรวจว่าพื้นที่จัดเก็บของฐานข้อมูลยังอยู่ครบ โดยเปิดแอปที่ใช้ฐานข้อมูลนั้นดูข้อมูลจริง

ข้อควรรู้และข้อจำกัดของ Docker

  • ตั้งเพดานขนาดบันทึกการทำงานไว้ตั้งแต่แรก เป็นการป้องกันที่ได้ผลกว่าการมาไล่ล้างทีหลัง
  • ล้างทีละประเภทและอ่านรายการที่จะถูกลบก่อนยืนยันเสมอ อย่าใช้คำสั่งกวาดทั้งหมดบนเครื่องที่ให้บริการอยู่
  • ตั้งการแจ้งเตือนเมื่อพื้นที่ดิสก์เหลือน้อย จะได้จัดการก่อนที่บริการจะหยุดเพราะเขียนไฟล์ไม่ได้

คำถามที่พบบ่อยเกี่ยวกับ Docker

ล้างแล้วบริการที่รันอยู่จะได้รับผลกระทบไหม

สิ่งที่กำลังทำงานอยู่จะไม่ถูกลบ แต่พื้นที่จัดเก็บที่ไม่มีอะไรใช้อยู่ ณ ขณะนั้นอาจถูกลบได้ จึงต้องตรวจรายการก่อนยืนยันทุกครั้ง

พื้นที่ยังไม่คืนหลังล้าง

ให้ตรวจขนาดของบันทึกการทำงานและพื้นที่จัดเก็บที่ยังถูกใช้อยู่ ทั้งสองส่วนนี้ไม่ถูกล้างด้วยคำสั่งล้างของที่ไม่ใช้

ควรตั้งล้างอัตโนมัติตามรอบหรือไม่

ตั้งได้และช่วยได้มาก แต่ควรจำกัดขอบเขตให้ชัด เช่น ล้างเฉพาะอิมเมจที่ไม่มีใครใช้และเก่ากว่าที่กำหนด ไม่ใช่ล้างทุกอย่างที่ไม่ได้ทำงานอยู่

อ่านเพิ่มเติมเกี่ยวกับ Docker

แชร์FacebookXLINELinkedIn

มีคำถามเรื่องบริการ? ติดต่อทีมงาน