如何以相对较小的磁盘 space 消耗量构建大型 docker 映像?

How to build a large docker image with relatively small disk space consumption?

背景

我正在尝试从 VM 上的 Docker 文件构建 docker 图像。 VM 是 运行ning Redhat 7.1(内核 3.10)并且 Docker 是 1.10.2

Docker文件有以下内容

FROM rhel
MAINTAINER MyName<me@email.com>
RUN #yum install wget and other tools (less than 500 MB)
COPY entitlementfile /opt/entitlementfile
RUN  wget -O /opt/installer.bin https://installer.com/installer.bin \ 
    && chmod +x /opt/* \
    && /opt/installer.bin --quiet \
    && rm -f /opt/*.bin
USER admin

我的构建 VM 有大约 16Gspace 可用

[root@xrh701 DockerImage]# df -h
Filesystem                                        Size  Used Avail Use% Mounted on
/dev/mapper/rhel-root                              18G  2.1G   16G  12% /
...

安装包在3G左右,安装包在8G左右。这加起来最大为 11G,略微超过 docker 默认的基本设备大小 10G。

所以我手动启动 docker 守护进程和更大的 dm.size (15G) 来解决这个问题。

docker daemon --storage-opt dm.basesize=15G

由于docker是基于Union FS的,图像是相互叠加的。 所以我的理解是

(1)我的镜像最大能到11G(安装一层3G,包层加在最上面8G)

(2) 如果我得到安装程序,运行 它,然后在相同的 运行 命令中删除安装程序,图像应该只有 8G(因为 3G 安装程序被删除)

无论如何,底线是,16G space 应该绰绰有余。

问题

但我目前的观察是,在我的 docker 构建过程中, 它总是会挂起,因为它已经消耗了所有可用的 spaces

[root@xrh701 DockerImage]# df -h
Filesystem                                        Size  Used Avail Use% Mounted on
/dev/mapper/rhel-root                              18G   18G   20K 100% /
...

我可以看到两张图片

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              fa09e98656ba        About an hour ago   258.1 MB
rhel                latest              32f8a1d5f019        9 days ago          203.2 MB

"docker inspect "说明图片是COPY授权文件后的中间图片。

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
232245023f90        fa09e98656ba        "/bin/sh -c 'wget -O "   About an hour ago   Exited (0) About an hour ago                       lonely_curie

此中间容器已完成 运行 wget 行,成功退出,但由于缺少 space

而未提交到 docker 图像

更糟糕的是,我无法删除容器,也无法删除 /var/lib/docker 来恢复 space 回来

# docker rm -f lonely_curie
Failed to remove container (lonely_curie): Error response from daemon: Driver devicemapper failed to remove root filesystem 232245023f90b42a4dbd19a78bf32836f9f8618d7dbcba54159c3df029b5b114: mount still active

问题

  1. 为什么docker用完了所有space?根据计算,磁盘space(16G)对于目标镜像(8G)应该绰绰有余。 [我拥有这个 VM,所以我可以保证没有其他人或任何其他进程正在消耗硬盘 space]

  2. 如何在当前情况下强制删除容器,以便恢复 space?

  3. 我应该如何在 16G VM 上构建这个 8G 映像(如果算上安装程序,则为 11G 映像)?如果这不可能,成功构建它的最小 space 是多少?我目前正在向实验室申请32G VM

TL;DR

假设安装程序为3G,安装包为8G。

如果我发布 Dokcerfile,那么构建此映像的最低磁盘要求至少为 22 G [ (3+8)*2 = 22 ]。

如果我发布镜像并推送到 Dockerhub,那么用户只需要 11 G 来拉取镜像和运行一个基于它的容器。

============================================= =====================

建造

我有一台大约 50G 的机器来重新运行 构建并监控磁盘消耗。

构建开始之前

# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root   59G   6G   53G  9% /
...

安装完成后

# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root   59G   19G   38G  34% /
...

提交图像后

# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root   59G   27G   30G  48% /
...

所以回答我自己的问题: (1) 它用完了所有磁盘,因为它至少需要那么多磁盘 space。之前的计算一厢情愿地假设 运行ning 容器和要构建的图像将共享同一层。

(2) 这部分还没想好。现在我只是扔掉虚拟机并让回收它。

(3) 所需的最小磁盘空间为 (3G + 8G) * 2 = 22 G。所以我想为了将来参考,我应该保留理论计算图像大小的两倍,因为该层似乎是a 将 运行ning 容器提交到图像时复制而不是共享。 [构建 Dockerfile 与手动 运行 构建容器并提交到映像基本相同。]

============================================= ====================

运行

然后跟进,我提交镜像删除容器后,可以回收磁盘

# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root   59G   15G   42G  26% /
....

从那时起,启动 运行ning 容器将不会(显着)增加磁盘消耗。

# df -h
Filesystem                 Size  Used Avail Use% Mounted on
/dev/mapper/vg_01-lv_root   59G   15G   42G  26% /
...