DeployEasy
Menu
ProductionTrung bình

Sửa lỗi No space left on device trên VPS và Docker

Hướng dẫn tìm nguyên nhân hết dung lượng hoặc inode, kiểm tra log, Docker image, volume, journal và dọn VPS an toàn không mất dữ liệu.

· 9 phút đọc · 1.922 từ
Mục lục bài viết

Lỗi:

No space left on device

không phải lúc nào cũng có nghĩa ổ đĩa hết GB. Linux có thể còn dung lượng nhưng hết inode, filesystem read-only hoặc Docker storage đầy.

Trên VPS dung lượng 20 GB, Docker image, build cache, database và log có thể lấp đầy ổ rất nhanh.

Triệu chứng

  • Không tạo được file.
  • Git pull fail.
  • npm install fail.
  • Docker build fail.
  • PostgreSQL dừng.
  • Nginx không ghi log.
  • App không upload file.
  • SSH hoạt động bất thường.
  • systemd service fail.

Ví dụ:

write /var/lib/docker/...: no space left on device

Bước 1: Kiểm tra dung lượng

df -h

Ví dụ:

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G   20G     0 100% /

Quan tâm mount point bị đầy, không chỉ tổng.

Nếu / đầy 100%, nhiều service có thể lỗi.

Bước 2: Kiểm tra inode

df -i

Ví dụ:

Filesystem     Inodes  IUsed IFree IUse% Mounted on
/dev/vda1      100000 100000     0  100% /

Hết inode nghĩa là không thể tạo file mới dù còn dung lượng byte.

Nguyên nhân:

  • Hàng triệu file cache.
  • Session file.
  • Mail queue.
  • node_modules.
  • Docker layers.
  • Log file nhỏ.
  • Temporary files.

Bước 3: Xác định mount bị đầy

findmnt
lsblk
df -hT

Có thể /var/lib/docker nằm trên mount riêng hoặc root partition.

Không dọn thư mục khác filesystem nếu mount đầy nằm nơi khác.

Bước 4: Tìm directory lớn

Cấp một dưới root:

sudo du -xhd1 / | sort -h

Nếu /var lớn:

sudo du -xhd1 /var | sort -h

Nếu Docker lớn:

sudo du -xhd1 /var/lib/docker | sort -h

-x giữ trong cùng filesystem.

Chạy du có thể tốn I/O trên server bận.

Bước 5: Tìm file lớn

sudo find / \
  -xdev \
  -type f \
  -size +500M \
  -printf '%s %p\n' 2>/dev/null |
sort -n

Hiển thị dễ đọc bằng numfmt:

sudo find / \
  -xdev \
  -type f \
  -size +500M \
  -printf '%s %p\n' 2>/dev/null |
sort -n |
numfmt --field=1 --to=iec

Không xóa trước khi xác định file thuộc service nào.

Docker chiếm dung lượng

Kiểm tra:

docker system df

Chi tiết:

docker system df -v

Xem:

  • Images.
  • Containers.
  • Local volumes.
  • Build cache.

Dọn stopped container

Liệt kê:

docker ps -a

Xóa container đã dừng mà không cần:

docker container prune

Lệnh hỏi xác nhận. Review trước.

Dọn dangling image

docker image prune

Dọn image không còn container tham chiếu:

docker image prune -a

-a có thể xóa image cũ cần rollback. Kiểm tra trước:

docker image ls

Dọn build cache

docker builder prune

Chi tiết:

docker buildx du

Dọn có giới hạn nếu phiên bản hỗ trợ:

docker builder prune \
  --filter 'until=168h'

Kiểm tra tài liệu Docker version hiện tại.

Dọn volume

Liệt kê:

docker volume ls

Xem volume không dùng:

docker volume ls -f dangling=true

Dọn:

docker volume prune

Cảnh báo: volume có thể chứa database hoặc file upload. Chỉ xóa sau khi xác minh và backup.

Không chạy:

docker system prune -a --volumes

một cách máy móc trên production.

Docker container log quá lớn

Docker json-file log thường nằm dưới:

/var/lib/docker/containers/

Tìm:

sudo find /var/lib/docker/containers \
  -name '*-json.log' \
  -type f \
  -printf '%s %p\n' |
sort -n |
tail

Không xóa file khi chưa hiểu daemon đang dùng.

Cấu hình rotation trong Compose:

logging:
  driver: json-file
  options:
    max-size: "10m"
    max-file: "3"

Hoặc daemon config:

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

Cấu hình mới thường áp dụng cho container tạo sau đó. Lên kế hoạch recreate.

systemd journal

Kiểm tra:

journalctl --disk-usage

Xóa log cũ theo thời gian:

sudo journalctl --vacuum-time=7d

Theo kích thước:

sudo journalctl --vacuum-size=500M

Đừng xóa toàn bộ log ngay trong lúc điều tra sự cố.

Cấu hình giới hạn trong:

/etc/systemd/journald.conf

Ví dụ:

SystemMaxUse=500M

Sau thay đổi:

sudo systemctl restart systemd-journald

Đánh giá tác động trước.

Nginx log

sudo du -sh /var/log/nginx/*

Logrotate:

cat /etc/logrotate.d/nginx

Test debug:

sudo logrotate -d /etc/logrotate.conf

Không dùng force rotation thiếu hiểu biết trên production.

PM2 log

pm2 logs
du -sh ~/.pm2/logs

Dùng logrotate:

pm2 install pm2-logrotate

Cấu hình retention/size theo tài liệu PM2.

PostgreSQL log và data

Kiểm tra:

sudo du -sh /var/lib/postgresql/*
sudo du -sh /var/log/postgresql/*

Không xóa file trong data directory thủ công.

Database lớn cần kiểm tra:

SELECT pg_size_pretty(
  pg_database_size(current_database())
);

Bảng lớn:

SELECT
  schemaname,
  relname,
  pg_size_pretty(
    pg_total_relation_size(
      quote_ident(schemaname) || '.' || quote_ident(relname)
    )
  ) AS total_size
FROM pg_stat_user_tables
ORDER BY pg_total_relation_size(
  quote_ident(schemaname) || '.' || quote_ident(relname)
) DESC
LIMIT 20;

Xóa row không tự làm file hệ điều hành nhỏ ngay. PostgreSQL dùng MVCC và vacuum; VACUUM FULL có lock và cần thêm disk tạm. Không chạy trên production thiếu kế hoạch.

Backup cũ

sudo du -sh /var/backups/*
find /var/backups -type f -mtime +30 -print

Chỉ xóa theo retention đã định nghĩa và bảo đảm có bản offsite.

Release cũ

Cấu trúc:

/var/www/app/releases/

Giữ 3–5 release gần nhất, xóa cũ sau khi xác minh rollback không cần.

Ví dụ liệt kê theo thời gian:

ls -1dt /var/www/app/releases/*

Không dùng pipeline xóa tự động nếu chưa xử lý tên file chứa space và số lượng release.

npm cache

Kiểm tra:

npm cache verify

Cache user:

du -sh ~/.npm

Dọn:

npm cache clean --force

Thường không phải bước đầu tiên; cache có thể giúp build. Chỉ dọn khi cần.

APT cache

sudo du -sh /var/cache/apt

Dọn package cache:

sudo apt clean

Xóa dependency không cần:

sudo apt autoremove

Review danh sách trước khi xác nhận.

File đã xóa nhưng dung lượng chưa trả

Một process có thể vẫn giữ file đã bị xóa mở.

Kiểm tra:

sudo lsof +L1

Ví dụ log lớn hiện (deleted) nhưng process vẫn giữ descriptor.

Dung lượng chỉ được trả khi process đóng file hoặc restart/reload phù hợp.

Không restart database/web server tùy tiện; xác định service và impact.

Hết inode

Tìm nơi có nhiều file:

sudo find /var \
  -xdev \
  -printf '%h\n' 2>/dev/null |
sort |
uniq -c |
sort -n |
tail -n 30

Hoặc đếm theo thư mục có kiểm soát.

Các nguồn:

  • Session.
  • Cache.
  • Mail.
  • Build output.
  • node_modules.
  • Docker overlay.

Không chỉ xóa file lớn, vì inode issue do số lượng file.

Reserved blocks

Ext filesystem có thể dành một phần block cho root. User thường thấy hết chỗ trước root.

Kiểm tra filesystem và reserved block bằng công cụ phù hợp, nhưng không giảm reserved percentage thiếu hiểu biết. Reserved space giúp root đăng nhập và sửa hệ thống khi disk gần đầy.

Filesystem read-only

Nếu có lỗi I/O, filesystem có thể remount read-only.

Kiểm tra:

mount | grep ' on / '
sudo journalctl -k \
  --since "30 minutes ago"

Thông báo:

I/O error
EXT4-fs error
Remounting filesystem read-only

Đây không chỉ là vấn đề dọn file; cần kiểm tra disk/hạ tầng và backup ngay.

Inotify watch không phải disk space

Một số lỗi:

ENOSPC: System limit for number of file watchers reached

Cũng có chữ ENOSPC nhưng không phải hết ổ đĩa.

Kiểm tra:

sysctl fs.inotify.max_user_watches

Đây là giới hạn inotify. Chỉ tăng sau khi hiểu app đang tạo watcher nào, đặc biệt development hot reload.

Safe cleanup workflow

1. Xác định loại

df -h
df -i

2. Xác định mount

findmnt

3. Xác định directory

sudo du -xhd1 /var | sort -h

4. Xác định service/file

docker system df
journalctl --disk-usage
sudo lsof +L1

5. Backup nếu là dữ liệu

Database, volume, upload.

6. Dọn bằng công cụ service

  • Docker commands.
  • journalctl vacuum.
  • logrotate.
  • retention script.
  • apt clean.

Không rm -rf vào data directory.

Ngăn lỗi tái diễn

Cảnh báo disk

Ví dụ threshold:

80% warning
90% critical

Cần theo dõi cả tốc độ tăng.

Cảnh báo inode

df -i

Log rotation

Nginx, PM2, Docker, journal.

Docker cleanup policy

Giữ image rollback cần thiết, dọn build cache theo lịch.

Backup retention

Không giữ vô hạn trên local disk.

Tách volume

Có thể tách:

/var/lib/docker
/var/lib/postgresql
/srv/uploads

sang disk riêng để giảm ảnh hưởng lẫn nhau.

Tăng disk

Nếu dữ liệu tăng thật, cleanup không đủ. Resize volume theo quy trình nhà cung cấp và filesystem.

Sau resize block device có thể cần mở rộng partition/filesystem. Cách làm phụ thuộc cloud và filesystem; backup trước.

Ví dụ VPS 20 GB

Phân bổ có thể:

Ubuntu + package: 4 GB
Docker images:     6 GB
Build cache:       4 GB
PostgreSQL:        3 GB
Log:               2 GB
Source/releases:   2 GB

Tổng đã vượt 20 GB.

Giải pháp:

  • Build image trong CI.
  • Không giữ build cache production.
  • Log rotation.
  • Backup offsite.
  • Giữ ít release/image.
  • Tăng disk khi dữ liệu tăng thật.

Không nên làm

Xóa /var/lib/docker

Có thể phá toàn bộ Docker state.

Xóa PostgreSQL WAL/data

Có thể làm database không phục hồi được.

Xóa mọi log ngay

Mất dữ liệu điều tra.

Chạy prune với --volumes

Có thể xóa database volume.

Chỉ tăng disk

Nếu log leak hoặc cache không giới hạn, disk mới cũng sẽ đầy.

Checklist khẩn cấp

[ ] df -h
[ ] df -i
[ ] Xác định mount đầy
[ ] du theo từng cấp
[ ] docker system df
[ ] journalctl --disk-usage
[ ] lsof +L1
[ ] Xác định dữ liệu quan trọng
[ ] Backup trước khi xóa
[ ] Dọn bằng công cụ đúng
[ ] Xác minh service sau dọn
[ ] Thiết lập rotation/retention
[ ] Tạo cảnh báo disk/inode

Câu hỏi thường gặp

Còn 5 GB nhưng vẫn báo no space?

Có thể hết inode, mount khác bị đầy, filesystem read-only hoặc giới hạn inotify.

Có nên chạy docker system prune -a?

Chỉ sau khi review image/container/cache cần giữ. Nó có thể xóa image rollback.

Xóa log file rồi sao disk chưa giảm?

Process có thể vẫn giữ file mở. Kiểm tra lsof +L1.

Swap có chiếm disk không?

Có. Swap file dùng dung lượng filesystem. Không xóa khi đang active; phải swapoff và cập nhật fstab đúng quy trình.

Kết luận

No space left on device cần phân biệt hết byte, hết inode, file deleted-open và filesystem error. Dọn đúng service và thiết lập rotation, retention, monitoring để lỗi không lặp lại.

Nguồn tham khảo

Đọc tiếp