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.
Mục lục bài viết
VPS & Hosting cho dự án của bạn
Khám phá các gói máy chủ và lưu trữ phù hợp từ website cá nhân đến ứng dụng production.
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
Bài viết liên quan
Monitoring production: Log, healthcheck, CPU, RAM và cảnh báo
Hướng dẫn monitoring VPS và ứng dụng production bằng journalctl, Nginx log, PM2, Docker healthcheck, tài nguyên và cảnh báo.
Đọc bài →Sửa lỗi Killed và exit code 137 khi build Docker, Next.js
Giải thích exit code 137, SIGKILL, Linux OOM Killer và cách kiểm tra RAM, swap, Docker limit khi build Next.js hoặc Node.js trên VPS.
Đọc bài →Backup và restore PostgreSQL production bằng pg_dump
Hướng dẫn backup PostgreSQL bằng pg_dump, định dạng custom, pg_restore, lịch cron, kiểm tra restore và lưu bản sao ngoài VPS.
Đọc bài →