为什么Docker容器映像如此之大?


177

我通过Fedora的Dockerfile创建了一个简单的映像(最初为320 MB)。

添加了Nano(这个1MB大小的微型编辑器),图像的大小已增加到530 MB。我在此基础上添加了Git(30-ish MB),然后将图像大小的火箭提高到830 MB。

那不是疯了吗?

我试图导出和导入容器以删除历史记录/中间图像。这项工作最多可节省25 MB,现在我的图像大小为804 MB。我也曾尝试在一个命令上运行许多命令RUN,但仍然获得相同的初始830MB。

我一直在怀疑是否值得使用Docker。我的意思是,我几乎没有安装任何东西,而我的可用空间已超过1GB。如果我必须添加一些重要的东西,例如数据库,等等,我可能会用完磁盘空间。

任何人都可笑的图像大小?你如何解决?

除非我的Dockerfile非常错误?

FROM fedora:latest
MAINTAINER Me NotYou <email@dot.com>
RUN yum -y install nano
RUN yum -y install git

但很难想象这里可能出什么问题。


您在哪里以及如何测量容器的尺寸?是否yum clean all有大小有什么影响?
xeor 2014年

2
期望图像尺寸合适,因为它是图像,父图像和基础图像的累积。另外,yum不仅安装了上述应用程序,还安装了它们的依赖项。docs.docker.com/terms/container
rexposadas

2
好吧,我的“测量”是执行docker images,在最后一栏中指出它的容量为830MB。我可能不知道实际上映像的实际大小是多少,因为docker images命令指出这830MB是虚拟大小。但是,图像的实际大小又是多少?
2014年

Answers:


118

正如@rexposadas所说,映像包括所有层,并且每个层都包括您所安装内容的所有依赖项。同样重要的是要注意,基本映像(例如fedora:latest往往是非常准系统的。您可能会对安装的软件所具有的依赖性数量感到惊讶。

通过添加yum -y clean all到每一行,我能够使您的安装大大减少:

FROM fedora:latest
RUN yum -y install nano && yum -y clean all
RUN yum -y install git && yum -y clean all

在提交层之前,对于每个RUN都必须这样做,否则删除实际上并不会删除数据。也就是说,在并集/写时复制文件系统中,最后的清理并没有真正减少文件系统的使用,因为实际数据已经提交给了较低的层。为了解决这个问题,您必须清洁每一层。

$ docker history bf5260c6651d
IMAGE               CREATED             CREATED BY                                      SIZE
bf5260c6651d        4 days ago          /bin/sh -c yum -y install git; yum -y clean a   260.7 MB
172743bd5d60        4 days ago          /bin/sh -c yum -y install nano; yum -y clean    12.39 MB
3f2fed40e4b0        2 weeks ago         /bin/sh -c #(nop) ADD file:cee1a4fcfcd00d18da   372.7 MB
fd241224e9cf        2 weeks ago         /bin/sh -c #(nop) MAINTAINER Lokesh Mandvekar   0 B
511136ea3c5a        12 months ago                                                       0 B

1
感谢您为调查此案所做的努力,是的,我能够将映像大小减小到大约635MB(这是在执行后显示为虚拟映像大小的值docker images)。是否可以删除/删除/销毁那些旧图层?更具体地说:我想从历史记录中完全删除(以您的示例为基础)图像:172743bd5d60、3f2fed40e4b0,fd241224e9cf,511136ea3c5a,以便我的虚拟图像大小与最终图像大小几乎相同,此处为〜260MB 。
2014年

(对于1条评论来说太长了)除非虚拟映像大小与HDD上映像的实际大小无关?如果是这种情况,那么如何/在哪里查看图像的实际大小?
2014年

你可以docker exportdocker import一次。那会弄平层。我不认为这会减小尺寸,但我可能是错的。
安迪

10
是的,但是出口并不能节省太多。尽管如此,我仍然能够通过网络阅读到我可以在docker中观察到的是虚拟映像大小。硬盘上的实际大小对我来说是个谜,因为从官方信息docker ps -s来看,硬盘上的实际大小是我的-1B。听起来不错,减去1 Byte。我已经在HDD上获得了一些空间...似乎合法。
2014年

@Zen对不起,我没有关注。那么虚拟大小和磁盘大小是两个不同的东西吗?虚拟尺寸究竟能衡量什么?
杰森

63

Docker映像并不大,您只是在构建大型映像。

scratch映像为0B,如果可以将代码编译为静态二进制文件,则可以使用该映像打包代码。例如,您可以编译Go程序并将其打包,scratch以制作一个小于5MB的完全可用的映像。

关键是不要使用正式的Docker映像,它们太大了。Scratch也不是很实用,因此我建议使用Alpine Linux作为基本映像。它约为5MB,然后仅添加您的应用所需的内容。这篇有关微容器的文章向您展示了如何基于Alpine构建非常小的图像。

更新:官方Docker映像现在基于alpine,因此现在很好使用。


2
伟大的解决方案!,停止浪费并保持更高的安全性--->减少代码->减少担忧非常重要。
Ran Davidovitz

1
值得庆幸的是,Docker Official映像也正在使用Alpine平台,因此越来越多的人可以使用常规映像,而不必依赖iron.io的版本。参见brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels,2016年

@Travis R,您发布的有关微型容器的链接似乎已经移到其他地方。是你的意思链接的帖子?
亚历山大·

@AlexanderF。固定链接,谢谢让我知道。
特拉维斯·里德

28

您还可以执行以下操作

  • 尽可能避免使用多个RUN命令。将尽可能多的内容放入一个RUN命令中(使用&&
  • 清理不必要的工具,例如wget或git(您只需要下载或构建它们,而无需运行进程)

通过这些和@Andy和@michau的建议,我能够将我的nodejs图像的大小从1.062 GB调整为542 MB。

编辑:另一件重要的事情: “花了一段时间我才真正了解到,每个Dockerfile命令都使用增量创建了一个新容器。它们继续存在于某些中间层容器中。” 所以,现在我设法把apt-get installwgetnpm install(用git的依赖),并apt-get remove成一个单一的RUN命令,所以现在我的形象只有438 MB。

编辑29/06/17

Docker v17.06新增了Dockerfile的新功能:您可以FROM在一个Dockerfile中包含多个语句,只有最后的内容FROM才会出现在最终的Docker映像中。这对于减小图像尺寸很有用,例如:

FROM nodejs as builder
WORKDIR /var/my-project
RUN apt-get install ruby python git openssh gcc && \
    git clone my-project . && \
    npm install

FROM nodejs
COPY --from=builder /var/my-project /var/my-project

第一步将产生一个仅包含nodejs基本映像以及/ var / my-project中的内容的映像-但包含ruby,python,git,openssh和gcc!


21

是的,这些大小太荒谬了,我真的不知道为什么很少有人注意到这一点。

我制作了一个实际上很小的Ubuntu映像(与其他所谓的“最小”映像不同)。它被称为textlab/ubuntu-essential具有60 MB。

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano

上图是安装nano后的82 MB。

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano git

Git有更多的先决条件,因此图像变得更大,大约192 MB。仍然比大多数图像的初始尺寸小。

您也可以看看我编写的脚本该脚本为Docker制作了最小的Ubuntu映像。您也许可以使其适应Fedora,但是我不确定您将能够卸载多少。


13

以下内容对我有很大帮助:

删除容器中未使用的软件包(例如,释放redis 1200 mb)后,我执行了以下操作:

  1. 码头工人出口[containerID] -o containername.tar
  2. docker import -m“在此处提交消息” containername.tar imagename:tag

图层变平。如上所述,新图像的尺寸将较小,因为我已从容器中移除了包装。

这花了很多时间来理解,这就是为什么我添加我的评论的原因。


您可以将两个步骤组合为一个步骤docker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar,

8

为了获得最佳实践,应该执行一个RUN命令,因为Dockerfile中的每个RUN指令都会在映像中写入一个新层,并且每个层都需要磁盘上的额外空间。为了使层数最少,理想情况下,任何文件操作(如安装,移动,提取,删除等)都应在单个RUN指令下进行

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all


0

是的,层系统非常令人惊讶。如果您有基本图像,则可以通过执行以下操作来增加它:

# Test
#
# VERSION       1

# use the centos base image provided by dotCloud
FROM centos7/wildfly
MAINTAINER JohnDo 

# Build it with: docker build -t "centos7/test" test/

# Change user into root
USER root

# Extract weblogic
RUN rm -rf /tmp/* \
    && rm -rf /wildfly/* 

图像尺寸完全相同。从本质上讲,这意味着您必须设法在运行步骤中进行很多提取,安装和清理操作,以使映像与安装的软件一样小。

这使生活更加艰难...

dockerBuild缺少没有提交的RUN步骤。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.