Docker占用的磁盘空间清理及优化和 none 镜像清理
1. docker system命令
在谁用光了磁盘?Docker System命令详解中,我们详细介绍了docker system命令,它可以用于管理磁盘空间。
docker system df命令,类似于Linux上的df命令,用于查看Docker的磁盘使用情况:
可知,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占用的磁盘空间减少了很多:
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)
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.
+++++++++++++++++++++++++++++++++++++
docker prune 命令
prune 命令用来删除不再使用的 docker 对象。
删除所有未被 tag 标记和未被容器使用的镜像:
$ docker image prune
WARNING! This will remove all dangling images.
Are you sure you want to continue? [y/N] y
默认情况下,系统会提示是否继续。要绕过提示,请使用 -f 或 --force 标志。
可以使用 --filter 标志使用过滤表达式来限制修剪哪些镜像。例如,只考虑 24 小时前创建的镜像:
# docker image prune -a --filter "until=24h"
删除所有未被容器使用的镜像(已验证):
$ docker image prune -a
删除所有停止运行的容器的镜像,也就是docker ps -a | grep Exited 的镜像。在Runn中的镜像是不会被删除。(已验证):
$ docker container prune
卷可以被一个或多个容器使用,并占用 Docker 主机上的空间。卷永远不会被自动删除,因为这么做会破坏数据。
$ docker volume prune
Docker 网络不会占用太多磁盘空间,但是它们会创建 iptables 规则,桥接网络设备和路由表条目。要清理这些东西,可以使用 docker network prune 来清理没有被容器未使用的网络。
$ docker network prune
docker system prune 命令是修剪镜像、容器和网络的快捷方式。在 Docker 17.06.0 及以前版本中,还好修剪卷。在 Docker 17.06.1 及更高版本中必须为 docker system prune 命令明确指定 --volumes 标志才会修剪卷。
$ docker system prune
如果使用 Docker 17.06.1 或更高版本,同时也想修剪卷,使用 --volumes 标志。
$ docker system prune --volumes
WARNING! This will remove:
- all stopped containers
- all networks not used by at least one container
- all volumes not used by at least one container
- all dangling images
- all build cache
Are you sure you want to continue? [y/N] y
none 镜像清理方法
删除none的镜像,要先删除镜像中的容器。要删除镜像中的容器,必须先停止容器。 $ docker images $ docker rmi $(docker images | grep "none" | awk '{print $3}') 直接删除带none的镜像,直接报错了。提示先停止容器。 $ docker stop $(docker ps -a | grep "Exited" | awk '{print $1 }') //停止容器 $ docker rm $(docker ps -a | grep "Exited" | awk '{print $1 }') //删除容器 $ docker rmi $(docker images | grep "none" | awk '{print $3}') //删除镜像