译者按: Docker镜像,容器,数据卷以及网络都会占用主机的磁盘空间,这样的话,磁盘很容易就会被用完。这篇博客介绍了一个简单的解决方案 - Docker System命令

原文: What’s eating my disk? Docker System Commands explained

译者: Fundebug

为了保证可读性,本文采用意译而非直译。

用了一段时间Docker后,会发现它占用了不少硬盘空间。还好Docker 1.13引入了解决方法,它提供了简单的命令来查看/清理Docker使用的磁盘空间。

本文通过一个简单的示例,可以证明Docker能够很快地将磁盘占满。该示例通过play-with-docker.com运行。点击Add new instance即可创建新的实例,该实例安装了最新版的Docker 17.03。这篇博客主要讨论磁盘空间,那么不妨使用df命令查看磁盘的初始状态:

$ df -h
Filesystem Size Used Available Use% Mounted on
/dev/mapper/... 10.0G 443.3M 9.6G 4% /
tmpfs 60.0G 0 60.0G 0% /dev
tmpfs 60.0G 0 60.0G 0% /sys/fs/cgroup
/dev/xvda1 49.1G 3.7G 43.3G 8% /etc/resolv.conf
/dev/xvda1 49.1G 3.7G 43.3G 8% /etc/hostname
/dev/xvda1 49.1G 3.7G 43.3G 8% /etc/hosts
shm 64.0M 0 64.0M 0% /dev/shm
/dev/mapper/... 10.0G 443.3M 9.6G 4% /graph/overlay2

可知,在新创建的[play-with-docker.com](http://labs.play-with-docker.com/)实例,一共有10GB磁盘空间,其中接近500MB已被占用。

接下来编写Dockerfile来创建一个镜像。这个镜像基于Alpine镜像;镜像将写入3个随机的文件,每个文件1GB,文件由dd命令生成;因为这个镜像并没有实际作用,因此CMD设为/bin/true

FROM alpine
RUN dd if=/dev/zero of=1g1.img bs=1G count=1
RUN dd if=/dev/zero of=1g2.img bs=1G count=1
RUN dd if=/dev/zero of=1g3.img bs=1G count=1
CMD /bin/true

运行docker build -t test .即可创建镜像,执行完成后将生成一个3GB的镜像。

$ docker image ls
REPOSITORY TAG CREATED SIZE
test latest 38 seconds ago 3.23GB
alpine latest 5 weeks ago 3.99MB

不难理解,该镜像占用了相应大小的磁盘空间。

$ df -h
Filesystem Size Used Available Use% Mounted on
/dev/mapper/... 10.0G 3.4G 6.5G 34% /

若只写入2个随机文件,则需要修改Dockerfile,删掉一行。为了避免构建镜像时使用缓存,我在dd命令之前添加了一行echo命令。

FROM alpine
RUN echo foo
RUN dd if=/dev/zero of=1g1.img bs=1G count=1
RUN dd if=/dev/zero of=1g2.img bs=1G count=1
# RUN dd if=/dev/zero of=1g3.img bs=1G count=1
CMD /bin/true

本来以为这样可以节省1GB磁盘空间,然而实际情况更加糟糕!

$ df -h
Filesystem Size Used Available Use% Mounted on
/dev/mapper/... 10.0G 5.4G 4.5G 54% /

旧的Docker镜像一直存在,最终磁盘空间会很快被用完。Docker 1.13引入了docker system df命令,类似于Linux上的df命令,用于查看Docker的磁盘使用情况。

$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 0 5.373GB 5.373GB (100%)
Containers 0 0 0B 0B
Local Volumes 0 0 0B 0B

可知,实例上一共有3个Docker镜像: apline镜像,包含3个1GB随机文件的镜像以及包含2个1GB随机文件的镜像。这些镜像占用了超过5GB磁盘空间。由于我们并没有基于这些镜像运行容器,所以它们都可以被删除,所以可回收的(RECLAIMABLE)磁盘空间为100%。使用docker run test运行test镜像再查看:

$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 1 5.373GB 3.225GB (60%)
Containers 1 0 0B 0B
Local Volumes 0 0 0B 0B

现在情况就不同了,我运行了一个容器,它执行/bin/true之后就很快退出了。这个容器绑定了test镜像,test镜像被标记为活跃(active)因而不能被删除,这导致可回收的磁盘空间变少了。

现在来清理一下磁盘空间。Docker提供了docker system prune,可以用于清理dangling镜像(参考What are Docker <none>:<none> images?)和容器,以及失效的数据卷和网络。

$ docker system prune
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 dangling images
Are you sure you want to continue? [y/N] y
Deleted Containers:
1cdf866157b4a97e151125af3c2a7f186a59b6f63807e2014ce1a00d68f44e1d
Deleted Images:
deleted: sha256:f59bb277...
deleted: sha256:695b8e70...
deleted: sha256:93b1cceb...
deleted: sha256:c74d6bcd...
deleted: sha256:df8b9bb1...
deleted: sha256:dfe8340f...
deleted: sha256:ce1ee654...
Total reclaimed space: 3.221GB

根据警告信息可知,这个命令会删除所有关闭的容器以及dangling镜像。示例中,含有3个1GB随机文件的镜像的名称被占用了,名称为:,为dangling镜像,因此会被删除。同时,所有的中间镜像也会被删除。这样的话,一共3GB的磁盘空间被回收了!

更进一步,使用-a选项可以做深度清理。这时我们会看到更加严重的WARNING信息:

$ 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 Images:
untagged: test:latest
deleted: sha256:c515ebfa2...
deleted: sha256:07302c011...
deleted: sha256:37c0c6474...
deleted: sha256:5cc2b6bc4...
deleted: sha256:b283b9c35...
deleted: sha256:8a8b9bd8b...
untagged: alpine:latest
untagged: alpine@sha256:58e1a1bb75db1...
deleted: sha256:4a415e366...
deleted: sha256:23b9c7b43...
Total reclaimed space: 2.151GB

这个命令将清理整个系统,并且只会保留真正在使用的镜像,容器,数据卷以及网络,因此需要格外谨慎。比如,我们不能在生产环境中运行prune -a命令,因为一些备用镜像(用于备份,回滚等)有时候需要用到,如果这些镜像被删除了,则运行容器时需要重新下载。

此时,所有未绑定容器的镜像将会被删除。由于第一次prune命令删除了所有容器,因此所有镜像(它们没有绑定任何容器)都会被删除。

$ df -h
Filesystem Size Used Available Use% Mounted on
/dev/mapper/... 10.0G 442.5M 9.6G 4% /

现在,已使用的磁盘空间又变成了4%。本文的示例只是冰山一角,因为一旦我们运行了真正的容器,并且使用了Docker数据卷和Docker网络,则磁盘空间将会更快用完。感兴趣的话,可以查看博客最后的视频(不要忘了订阅!)。在视频中,我介绍一个简单的WordPress应用,它由数个容器,数据卷以及网络构成。这个应用可以很快地消耗掉磁盘空间,我将介绍如何处理这个问题。

视频: What's eating my disk?!Clean up your Docker System

关于Fundebug

Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。
自从2016年双十一正式上线,Fundebug累计处理了6亿+错误事件,得到了Google、360、金山软件等众多知名用户的认可。欢迎免费试用!

版权声明:

转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/04/19/docker-system-explain/

谁用光了磁盘?Docker System命令详解的更多相关文章

  1. LINUX的磁盘管理du命令详解

    LINUX的磁盘管理du命令详解 du(disk usage)命令可以计算文件或目录所占的磁盘空间.没有指定任何选项时, 它会测量当前工作目录与其所有子目录,分别显示各个目录所占的快数,最后才显示工作 ...

  2. Docker常用命令详解

    docker ps 查看当前正在运行的容器 docker ps -a 查看所有容器的状态 docker start/stop id/name 启动/停止某个容器 docker attach id 进入 ...

  3. 附003.Docker Compose命令详解

    一 Docker Compose命令格式 Usage: docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...] docker- ...

  4. docker基础命令详解

    Commands: attach    Attach to a running container build     Build an image from a Dockerfile commit  ...

  5. linux磁盘分区fdisk命令详解

    1.什么是分区?    分区是将一个硬盘驱动器分成若干个逻辑驱动器,分区是把硬盘连续的区块当做一个独立的磁硬使用.分区表是一个硬盘分区的索引,分区的信息都会写进分区表.2.为什么要有多个分区? 防止数 ...

  6. Docker dockerfile命令详解

    docker-file 官网文档:https://docs.docker.com/v17.09/engine/reference/builder/ 制作Dockerfile为Docker入门学习的第一 ...

  7. Docker(12)- docker run 命令详解

    如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 作用 创建一个新的容器并运行一个 ...

  8. Docker(11)- docker ps 命令详解

    如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 作用 列出容器 语法格式 doc ...

  9. Docker(24)- docker login 命令详解

    如果你还想从头学起 Docker,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1870863.html 作用 登录 Docker 镜像仓 ...

随机推荐

  1. 使用GDI绘制一条直线

    这个是绘制一条直线的代码 private void Form1_Load(object sender, EventArgs e)        {            //一根笔 颜色  一张纸  ...

  2. JS中的this 指向问题

    我发现在对JS的学习中有很多朋友对this的指向问题还是有很大的误区或者说只是大致了解,但是一旦遇到复杂的情况就会因为this指向问题而引发各种bug. 对于之前学习过c或者是Java的朋友来说可能这 ...

  3. wxpython tab切换页面

    最近没事学习下wxpython,发现很少有关于页面切换的demo,这边分享下2中切换的方法.第一种:利用wx.Notebook第二种:利用Sizer布局实现(自己写的),代码没有涉及到什么重构之类的优 ...

  4. 安装Eclipse(android)新建项目时遇到的问题

    ---恢复内容开始--- 解决方案: 我先删掉了新建的项目,重新建立项目时 将API都选成相同的API19:... 然后就成功了 ---恢复内容结束---

  5. C++类对象大小的计算

    (一)常规类大小计算 C++类对象计算需要考虑很多东西,如成员变量大小,内存对齐,是否有虚函数,是否有虚继承等.接下来,我将对此举例说明. 以下内存测试环境为Win7+VS2012,操作系统为32位 ...

  6. iOS网络编程笔记——Socket编程

    一.什么是Socket通信: Socket是网络上的两个程序,通过一个双向的通信连接,实现数据的交换.这个双向连路的一端称为socket.socket通常用来实现客户方和服务方的连接.socket是T ...

  7. Chrome 下动画卡顿问题的另一种可能

    [现象] 动画出现了明显的卡顿,且仅仅出现在 chrome 中. [原因排查] 一开始使用了css动画的时候已经出现了卡顿.找到如下的文章:CSS3 动画卡顿解决方案.深入浏览器理解CSS anima ...

  8. nodejs npm常用命令 转

    npm是一个node包管理和分发工具,已经成为了非官方的发布node模块(包)的标准.有了npm,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包. 1.npm install m ...

  9. Python快速入门(1)

    FROM:实验楼 http://python.usyiyi.cn/python_278/tutorial/index.html http://woodpecker.org.cn/abyteofpyth ...

  10. MYSQL数据库-约束

    约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性.唯一性. MYSQL中,常用的几种约束: 约束类型: 主键 默认值 唯一 外键 非空 关键字: PRIMARY KEY DEF ...