原文鏈接:https://yq.aliyun.com/articles/272173
用戶在使用 Docker 部署業務一段時間后,可能會發現宿主節點的磁盤容量持續增長,甚至將磁盤空間耗盡進而引發宿主機異常,進而對業務造成影響。 本文先對 Docker 的空間分析與清理進行說明,然后對容器的磁盤容量限制與使用建議做簡要說明。
典型問題場景
用戶發現 Docker 宿主機的磁盤空間使用率非常高。通過 du 逐層分析,發現是 Volume 或 overlay2 等目錄占用了過高空間。示例如下:
# 根據使用的存儲驅動的不同,相應目錄會有所不同: [root@node3 docker]# du -h --max-depth=1 |sort 104K ./network 13M ./image 20K ./plugins 24G ./overlay2 # 這個目錄占用了非常高的磁盤磁盤空間 25G . 283M ./volumes 4.0K ./swarm 4.0K ./tmp 4.0K ./trust 518M ./containers
空間使用分析
遇到此類問題,可以參閱如下步驟進行空間分析,定位占用過高空間的業務來源。
分析 Docker 空間分布
Docker 的內置 CLI 指令 docker system df
,可用於查詢鏡像(Images)、容器(Containers)和本地卷(Local Volumes)等空間使用大戶的空間占用情況。 示例輸出如下:
[root@node3 docker]# docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 17 12 2.713 GB 1.144 GB (42%) Containers 15 12 10.75 GB 0 B (0%) Local Volumes 8 4 282.9 MB 241.8 MB (85%)
查看空間占用細節
可以進一步通過 -v
參數查看空間占用細節,以確定具體是哪個鏡像、容器或本地卷占用了過高空間。示例輸出如下:
[root@node3 docker]# docker system df -v # 鏡像的空間使用情況 Images space usage: REPOSITORY TAG IMAGE ID CREATED SIZE SHARED SIZE UNIQUE SIZE CONTAINERS busybox latest 6ad733544a63 5 days ago 1.129 MB 0 B 1.129 MB 1 nginx latest b8efb18f159b 3 months ago 107.5 MB 107.5 MB 0 B 4 ubuntu latest 14f60031763d 3 months ago 119.5 MB 0 B 119.5 MB 0 alpine 3.3 606fed0878ec 4 months ago 4.809 MB 0 B 4.809 MB 0 tutum/curl latest 01176385d84a 3 years ago 224.4 MB 0 B 224.4 MB 1 # 容器的空間使用情況 Containers space usage: CONTAINER ID IMAGE COMMAND LOCAL VOLUMES SIZE CREATED STATUS NAMES d1da451ceeab busybox "ping 127.0.0.1" 0 10.7 GB About an hour ago Up About an hour dstest 956ae1d241e8 nginx:latest "nginx -g 'daemon ..." 0 26 B 3 months ago Up 3 months localTest_restserver_2 74973d237a06 nginx:latest "nginx -g 'daemon ..." 0 2 B 3 months ago Up 3 months # 本地卷的空間使用情況 Local Volumes space usage: VOLUME NAME LINKS SIZE 83ba8747f4172a3c02a15f85b71e1565affca59f01352b4a94e0d28e65c26d1c 0 830 B a479c303b278f1442f66644f694a554aac630e72b7a27065a11ef85c4d87b648 0 22.16 MB 79a25b6376e0d6587d8f4f24e08f9467981f04daad14bf3353a12d727d065503 1 18.83 MB
空間清理
自動清理
可以通過 Docker 內置的 CLI 指令 docker system prune
來進行自動空間清理。
Tips :
不同狀態的鏡像
- 已使用鏡像(used image): 指所有已被容器(包括已停止的)關聯的鏡像。即 docker ps -a 看到的所有容器使用的鏡像。
- 未引用鏡像(unreferenced image):沒有被分配或使用在容器中的鏡像,但它有 Tag 信息。
- 懸空鏡像(dangling image):未配置任何 Tag (也就無法被引用)的鏡像,所以懸空。這通常是由於鏡像 build 的時候沒有指定 -t 參數配置 Tag 導致的。比如:
REPOSITORY TAG IMAGE ID CREATED SIZE <none> <none> 6ad733544a63 5 days ago 1.13 MB # 懸空鏡像(dangling image)
掛起的卷(dangling Volume)
類似的,dangling=true 的 Volume 表示沒有被任何容器引用的卷。
docker system prune 自動清理說明:
-
該指令默認會清除所有如下資源:
- 已停止的容器(container)
- 未被任何容器所使用的卷(volume)
- 未被任何容器所關聯的網絡(network)
- 所有懸空鏡像(image)。
- 該指令默認只會清除懸空鏡像,未被使用的鏡像不會被刪除。
- 添加
-a 或 --all
參數后,可以一並清除所有未使用的鏡像和懸空鏡像。 - 可以添加
-f 或 --force
參數用以忽略相關告警確認信息。 - 指令結尾處會顯示總計清理釋放的空間大小。
操作示例:
[root@node3 docker]# docker system prune --help Usage: docker system prune [OPTIONS] Remove unused data Options: -a, --all Remove all unused images not just dangling ones -f, --force Do not prompt for confirmation --help Print usage [root@node3 docker]# docker system prune -a WARNING! This will remove: - all stopped containers - all volumes not used by at least one container - all networks not used by at least one container - all images without at least one container associated to them Are you sure you want to continue? [y/N] y Deleted Containers: c09c31c49491ee7f2324160e43947917940221b4e6cc1274906def640a7a631f 2aa0180e1a0f4c2c64349a6ed969651052373e7a9471050dce9015701cf1b957 6d18003b06823c5d76d807a319387b06680fc93d0a32bc29c1cea4c07e8d515d Deleted Volumes: a479c303b278f1442f66644f694a554aac630e72b7a27065a11ef85c4d87b648 79a25b6376e0d6587d8f4f24e08f9467981f04daad14bf3353a12d727d065503 Deleted Images: untagged: tutum/curl:latest untagged: tutum/curl@sha256:b6f16e88387acd4e6326176b212b3dae63f5b2134e69560d0b0673cfb0fb976f deleted: sha256:01176385d84aeb1d40ed18c6d3f952abf40d2d2b4aa98fcf0a8a4b01010fb9a9 deleted: sha256:c84f85637212412c1d46d1dd50f789df2c3b44678ee3fee6a820888e734f9b5a untagged: test:lastest deleted: sha256:794ff09332586a091514eb3d1c44990244e57e34adc71d4b4334c0674a1377e9 deleted: sha256:636a1e7769d2242556243e9a21fb96bb878ab5b94c41ff485667252c968b375e Total reclaimed space: 1.565 GB
手工清理
網絡清理
網絡配置通常占用的空間非常低,略過。
鏡像清理
如果通過 docker system df 分析,是鏡像占用了過高空間。則可以根據業務情況,評估相關鏡像的使用情況。對於懸空和未使用的鏡像, 可以使用如下指令手工清理:
# 刪除所有懸空鏡像,但不會刪除未使用鏡像: docker rmi $(docker images -f "dangling=true" -q) # 刪除所有未使用鏡像和懸空鏡像。 # 【說明】:輪詢到還在被使用的鏡像時,會有類似"image is being used by xxx container"的告警信息,所以相關鏡像不會被刪除,忽略即可。 docker rmi $(docker images-q)
卷清理
如果通過 docker system df 分析,是卷占用了過高空間。則可以根據業務情況,評估相關卷的使用情況。對於未被任何容器調用的卷(-v 結果信息中,"LINKS" 顯示為 0),可以使用如下指令手工清理:
# 刪除所有未被任何容器關聯引用的卷: docker volume rm $(docker volume ls -qf dangling=true) # 也可以直接使用如下指令,刪除所有未被任何容器關聯引用的卷(但建議使用上面的方式) # 【說明】輪詢到還在使用的卷時,會有類似"volume is in use"的告警信息,所以相關卷不會被刪除,忽略即可。 docker volume rm $(docker volume ls -q)
容器清理
如果通過 docker system df 分析,是某個容器占用了過高空間。則可以根據業務情況,評估相關容器的業務歸屬並進行處理。對於已停止或其它異常狀態的容器,可以結合 -f 或 --filter
篩選器,使用類似如下指令來手工清理:
# 刪除所有已退出的容器 docker rm -v $(docker ps -aq -f status=exited) # 刪除所有狀態為 dead 的容器 docker rm -v $(docker ps -aq -f status=dead)
更多關於 ps 指令支持的篩選器信息,可以參閱官方文檔。
在用空間資源分析
對於還在使用的空間資源,可以參閱如下說明做進一步排查分析。
鏡像空間分析
如果某個鏡像占用了過高空間,則可以通過如下方式做進一步空間分析:
- 通過 docker system df 獲取占用過高空間的鏡像信息。
- 基於相應鏡像創建測試容器。
- exec 進入容器后,結合 du 等 shell 指令做進一步空間分析,定位出占用最高空間的目錄或文件。
- 結合業務情況做進一步處理,重新 build 鏡像。
示例:
[root@node3]# docker exec -it dstest sh / # du -h | head 8.0K ./root 32.0K ./etc 4.0K ./usr/sbin 8.0K ./usr 10.0G ./home/java/logs 10.0G ./home/java 10.0G ./home 1.1M ./bin 0 ./dev/shm 0 ./dev/mqueue
容器空間分析
如果某個運行中的容器占用了過高空間,則可以通過如下方式做進一步空間分析:
Tips :
容器的只讀層與鏡像層的空間占用情況
一個容器的占用的總空間,包含其最頂層的讀寫層(writable layer)和底部的只讀鏡像層(base image layer,read-only)。更多相關說明,可以參閱官方文檔。
可以通過 docker ps 的-s
參數來分別顯示二者的空間占用情況,進而判斷相應容器的空間占用主要是來自原始鏡像,還是運行中產生。
示例:
# 如下容器的原始鏡像占用了 422MB 空間,實際運行過程中只占用了 2B 空間: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE ac39128ccbc0 registry.aliyuncs.com/acs-sample/wordpress:4.6 "/entrypoint.sh ap..." 3 months ago Up 11 days 0.0.0.0:32779->80/tcp Web_web_4 2 B (virtual 422 MB)
容器空間占用的分析步驟:
- 通過 docker system df 獲取占用過高空間的容器信息。
- 通過前述
-s
參數確認到底是底層鏡像,還是運行過程中產生的數據占用了過高空間。 - exec 進入容器,結合 du 等 shell 指令做進一步空間分析,定位出占用最高空間的目錄或文件。
- 結合業務情況做進一步處理。
引申:Docker 磁盤空間限制與使用建議
磁盤空間限制
使用 Device Mapper 存儲驅動限制容器磁盤空間
如果使用 Device Mapper 作為底層存儲驅動,則可以通過 Docker daemon 的如下參數來全局限制單個容器占用空間的大小:
--storage-opt dm.basesize=20G
表示限制單個容器最多占用 20G 空間,將應用於任何新建容器。
更多關於 Device Mapper 存儲驅動的說明,可以參閱官方文檔。
使用 btrfs 存儲驅動限制容器磁盤空間
btrfs 驅動主要使用 btrfs 所提供的 subvolume 功能來實現。一個容器會對應一個 subvolume。針對容器對應的 subvolume 啟用並配置 quota 即可限制其磁盤空間。示例配置:
btrfs qgroup limit -e 50G /var/lib/docker/btrfs/subvolumes/<CONTAINER_ID>
btrfs 還有其它很好的特性,比如可以在線擴容(在線加入一塊新的塊設備,來擴充整個文件系統的大小)。更多關於 btrfs 存儲驅動的說明,可以參閱官方文檔。
外掛 LVM 卷
如果使用的是其它不支持對單個容器的磁盤容量進行限制的存儲驅動,則可以考慮如下通用方案:
- 通過 LVM 方式創建一個指定容量的卷,然后掛載到宿主操作系統上特定目錄。最后通過 --volume 參數來讓容器來掛載使用相應目錄。
注意:該方案的前提條件是,容器中所有落盤操作要全部落到上述 "--volume" 參數指定的卷中,否則容器還會占用默認 aufs 所在盤的空間,進而造成統計不准。
Docker 存儲使用建議
細化的存儲使用最佳實踐與采用的存儲驅動(storage driver)類型強相關,您可以參閱官方文檔做相關了解,本文不做進一步細化說明。
通用的存儲使用建議如下:
- 容器內的業務日志務必配置輪詢覆寫,或者使用日志驅動將日志輸出到外部存儲。避免日志文件持續增長,占用過高磁盤空間。
- 結合外部監控對宿主機的磁盤空間使用情況進行監控和告警。
- 可以參閱文檔 如何給容器服務的Docker增加數據盤來擴容默認 Docker 存儲空間。