1. 程式人生 > >如何清理Docker占用的磁盤空間?

如何清理Docker占用的磁盤空間?

ike logging uci 1.4 什麽 nta .com 應該 百萬

摘要:用了Docker,好處挺多的,但是有一個不大不小的問題,它會一不小心占用太多磁盤,這就意味著我們必須及時清理。


技術分享圖片

作為一個有信仰的技術公司,我們Fundebug的後臺采用了酷炫的全Docker化架構,所有服務,包括數據庫都運行在Docker裏面。這樣做當然不是為了炫技,看得清楚的好處還是不少的:

  • 所有服務器的配置都非常簡單,只安裝了Docker,這樣新增服務器的時候要簡單很多。
  • 可以非常方便地在服務器之間移動各種服務,下載Docker鏡像就可以運行,不需要手動配置運行環境。
  • 開發/測試環境與生產環境嚴格一致,不用擔心由於環境問題導致部署失敗。

至少,上線這一年多來,Docker一直非常穩定,沒有出什麽問題。但是,它有一個不大不小的問題,會比較消耗磁盤空間。

如果Docker一不小心把磁盤空間全占滿了,你的服務也就算玩完了,因此所有Docker用戶都需要對此保持警惕。當然,大家也不要緊張,這個問題還是挺好解決的。

1. docker system命令

在誰用光了磁盤?Docker System命令詳解中,我們詳細介紹了docker system命令,它可以用於管理磁盤空間。

docker system df命令,類似於Linux上的df命令,用於查看Docker的磁盤使用情況:

docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 147 36 7.204GB 3.887GB (53%)
Containers 37 10 104.8MB 102.6MB (97%)
Local Volumes 3 3 1.421GB 0B (0%)
Build Cache 0B 0B

可知,Docker鏡像占用了7.2GB磁盤,Docker容器占用了104.8MB磁盤,Docker數據卷占用了1.4GB磁盤。

docker system prune命令可以用於清理磁盤,刪除關閉的容器、無用的數據卷和網絡,以及dangling鏡像(即無tag的鏡像)。docker system prune -a命令清理得更加徹底,可以將沒有容器使用Docker鏡像都刪掉。註意,這兩個命令會把你暫時關閉的容器,以及暫時沒有用到的Docker鏡像都刪掉了…所以使用之前一定要想清楚吶。

執行docker system prune -a命令之後,Docker占用的磁盤空間減少了很多:

docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 10 10 2.271GB 630.7MB (27%)
Containers 10 10 2.211MB 0B (0%)
Local Volumes 3 3 1.421GB 0B (0%)
Build Cache 0B 0B

2. 手動清理Docker鏡像/容器/數據卷

對於舊版的Docker(版本1.13之前),是沒有docker system命令的,因此需要進行手動清理。這裏給出幾個常用的命
刪除所有關閉的容器

docker ps -a | grep Exit | cut -d ‘ ‘ -f 1 | xargs docker rm

刪除所有dangling鏡像(即無tag的鏡像):

docker rmi $(docker images | grep "^<none>" | awk "{print $3}")

刪除所有dangling數據卷(即無用的volume):

docker volume rm $(docker volume ls -qf dangling=true)

Fundebug提供實時、專業的錯誤監控服務,為您的線上代碼保駕護航,歡迎大家免費使用!

3. 限制容器的日誌大小

有一次,當我使用1與2提到的方法清理磁盤之後,發現並沒有什麽作用,於是,我進行了一系列分析。

在Ubuntu上,Docker的所有相關文件,包括鏡像、容器等都保存在/var/lib/docker/目錄中:

du -hs /var/lib/docker/
97G /var/lib/docker/

Docker竟然使用了將近100GB磁盤,這也是夠了。使用du命令繼續查看,可以定位到真正占用這麽多磁盤的目錄:

92G	/var/lib/docker/containers/a376aa694b22ee497f6fc9f7d15d943de91c853284f8f105ff5ad6c7ddae7a53

docker ps可知,nginx容器的ID恰好為a376aa694b22,與上面的目錄/var/lib/docker/containers/a376aa694b22的前綴一致:

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a376aa694b22 192.168.59.224:5000/nginx:1.12.1 "nginx -g ‘daemon off" 9 weeks ago Up 10 minutes nginx

因此,nginx容器竟然占用了92GB的磁盤。進一步分析可知,真正占用磁盤空間的是nginx的日誌文件。那麽這就不難理解了。我們Fundebug每天的數據請求為百萬級別,那麽日誌數據自然非常大。

使用truncate命令,可以將nginx容器的日誌文件“清零”:

truncate -s 0 /var/lib/docker/containers/a376aa694b22ee497f6fc9f7d15d943de91c853284f8f105ff5ad6c7ddae7a53/*-json.log

當然,這個命令只是臨時有作用,日誌文件遲早又會漲回來。要從根本上解決問題,需要限制nginx容器的日誌文件大小。這個可以通過配置日誌的max-size來實現,下面是nginx容器的docker-compose配置文件:

nginx:
image: nginx:1.12.1
restart: always
logging:
driver: "json-file"
options:
max-size: "5g"

重啟nginx容器之後,其日誌文件的大小就被限制在5GB,再也不用擔心了~

4. 重啟Docker

還有一次,當我清理了鏡像、容器以及數據卷之後,發現磁盤空間並沒有減少。根據Docker disk usage提到過的建議,我重啟了Docker,發現磁盤使用率從83%降到了19%。根據高手指點,這應該是與內核3.13相關的BUG,導致Docker無法清理一些無用目錄:

it’s quite likely that for some reason when those container shutdown, docker couldn’t remove the directory because the shm device was busy. This tends to happen often on 3.13 kernel. You may want to update it to the 4.4 version supported on trusty 14.04.5 LTS.

The reason it disappeared after a restart, is that daemon probably tried and succeeded to clean up left over data from stopped containers.

我查看了一下內核版本,發現真的是3.13:

uname -r
3.13.0-86-generic

如果你的內核版本也是3.13,而且清理磁盤沒能成功,不妨重啟一下Docker。當然,這個晚上操作比較靠譜。

參考

  • 誰用光了磁盤?Docker System命令詳解
  • INTRODUCING DOCKER 1.13
  • Docker文檔:docker system
  • Docker文檔:json-file
  • Docker disk usage

技術分享圖片

如何清理Docker占用的磁盤空間?