Sự cố 2 giờ sáng: Khi lệnh df -h hiện con số 99%
Chuông điện thoại reo dồn dập. Mình bật dậy, mắt nhắm mắt mở kiểm tra hệ thống khi server production báo lỗi 500 hàng loạt. Truy cập SSH chậm như rùa bò. Khi gõ lệnh df -h, phân vùng /var/lib/docker hiện đỏ chót với con số 99%. Thủ phạm không phải database hay log ứng dụng, mà chính là Docker.
Sau vài tháng chạy CI/CD liên tục, hàng trăm Image cũ và Volume “mồ côi” đã âm thầm chiếm sạch 150GB ổ cứng của mình. Nếu bạn đang gặp tình cảnh này, hãy cùng mình “tổng vệ sinh” hệ thống một cách an toàn và chuyên nghiệp.
Tại sao Docker lại “tham lam” dung lượng đến vậy?
Docker có tính giữ lại mọi thứ trừ khi bạn ra lệnh xóa. Mỗi lần docker build, các layer mới được tạo ra. Nếu build lỗi hoặc cập nhật bản mới, các layer cũ sẽ biến thành dangling images (image không tên, không tag). Chúng nằm đó như những bóng ma chiếm dụng bộ nhớ.
Bên cạnh đó, container đã dừng (Exited) vẫn chiếm không gian để lưu trạng thái. Nguy hiểm nhất là Volumes. Khi bạn xóa container, volume chứa dữ liệu thực tế không hề mất đi mà cứ tích tụ dần qua năm tháng.
Bước 1: Định vị “kẻ trộm” dung lượng
Đừng vội xóa mù quáng. Hãy kiểm tra xem Docker đang dùng bao nhiêu tài nguyên bằng lệnh:
docker system df
Kết quả thực tế từ một server mình từng xử lý:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 24 5 12.5GB 10.2GB (81%)
Containers 15 2 1.2GB 1.1GB (91%)
Local Volumes 40 10 25GB 15GB (60%)
Build Cache 102 0 5.4GB 5.4GB
Nhìn vào cột RECLAIMABLE, bạn sẽ thấy con số có thể “đòi lại” được. Như ví dụ trên, mình có thể giải phóng ngay lập tức hơn 30GB rác.
Bước 2: Quét sạch Container đã dừng
Nhiều anh em có thói quen chạy container test rồi bỏ đó. Các container này dù không chạy vẫn chiếm dung lượng đĩa. Để xóa toàn bộ container không hoạt động, hãy dùng:
docker container prune
Nếu muốn cẩn thận hơn, chỉ xóa các container đã dừng lâu hơn 24 giờ để tránh ảnh hưởng các task đang tạm nghỉ:
docker container prune --filter "until=24h"
Bước 3: Xử lý Docker Images dư thừa
Image thường là thành phần ngốn đĩa nhất. Bạn cần phân biệt hai loại:
- Dangling images: Image không có tag, thường sinh ra do build đè phiên bản cũ.
- Unused images: Image có tag nhưng không có container nào đang sử dụng.
Xóa các dangling images cực nhanh bằng:
docker image prune
Để dọn sạch tất cả image không dùng đến (kể cả image bạn vừa pull về nhưng chưa run), hãy dùng tham số -a. Kinh nghiệm của mình trên production là luôn dùng kèm filter thời gian để an toàn:
docker image prune -a --filter "until=72h"
Bước 4: Giải quyết “hố đen” Volumes
Volumes chứa dữ liệu quan trọng như database hay file upload. Docker cực kỳ thận trọng nên sẽ không bao giờ tự xóa volume. Những volume không gắn với container nào được gọi là dangling volumes.
Hãy liệt kê danh sách volume mồ côi trước khi ra quyết định:
docker volume ls -f dangling=true
Nếu xác định dữ liệu đó không còn giá trị, hãy dọn dẹp chúng:
docker volume prune
Cảnh báo: Luôn backup dữ liệu trước khi thực hiện. Xóa nhầm volume database là thảm họa không thể cứu vãn.
Lệnh “tổng lực”: Docker System Prune
Bạn muốn dọn dẹp mọi thứ trong một nốt nhạc? Docker cung cấp lệnh “hủy diệt” sau:
docker system prune
Lệnh này sẽ xóa sạch container đã dừng, network không dùng và dangling images. Tuy nhiên, nó mặc định không xóa volumes. Để tổng vệ sinh triệt để cả volume và image cũ, hãy dùng:
docker system prune -a --volumes
Trên môi trường Staging, mình thường chạy lệnh này hàng tuần. Kết quả thường rất ấn tượng, có lần mình lấy lại được 40% dung lượng đĩa chỉ sau 5 giây.
Quy trình duy trì server luôn “sạch”
Đừng đợi đến khi server báo đỏ mới đi dọn rác. Hãy áp dụng 4 quy tắc vàng sau:
- Dùng Flag
--rm: Khi chạy container tạm thời để test hoặc debug, hãy thêm--rmđể Docker tự xóa container ngay khi thoát.docker run --rm alpine echo "Dọn dẹp tự động" - Tích hợp vào CI/CD: Thêm bước
docker image prunevào cuối script deploy để xóa image cũ ngay sau khi bản mới lên sóng. - Cấu hình Log Rotation: Docker log có thể phình to hàng chục GB. Hãy giới hạn dung lượng log trong
/etc/docker/daemon.json:"log-driver": "json-file", "log-opts": {"max-size": "10m", "max-file": "3"} - Thiết lập Cronjob: Chạy
docker system pruneđịnh kỳ vào cuối tuần cho các server không quá khắt khe về uptime.
Hy vọng những kinh nghiệm thực chiến này giúp bạn quản lý Docker hiệu quả hơn. Chúc các bạn có những giấc ngủ ngon mà không bị đánh thức bởi tiếng chuông báo đầy ổ cứng!
