摘要:用了 Docker,好处挺多的,但是有一个不大不小的问题,它会一不小心占用太多磁盘,这就意味着我们必须及时清理。

如何清理Docker占用的磁盘空间?-LMLPHP

作为一个有信仰的技术公司,我们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 无法清理一些无用目录:

我查看了一下内核版本,发现真的是 3.13:

uname -r
3.13.0-86-generic

如果你的内核版本也是 3.13,而且清理磁盘没能成功,不妨重启一下 Docker。当然,这个晚上操作比较靠谱。

参考

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java线上应用实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了10亿+错误事件,付费客户有Google、360、金山软件、百姓网等众多品牌企业。欢迎大家免费试用

如何清理Docker占用的磁盘空间?-LMLPHP

转载时请注明作者Fundebug以及本文地址:https://blog.fundebug.com/2018/01/10/how-to-clean-docker-disk/

04-08 12:30