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

Zen*_*Zen 164 docker

我通过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
Run Code Online (Sandbox Code Playgroud)

但很难想象这里会出现什么问题.

And*_*ndy 112

正如@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 Code Online (Sandbox Code Playgroud)

在提交图层之前,为每个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
Run Code Online (Sandbox Code Playgroud)

  • 是的但出口并没有节省多少.尽管如此,我能够通过网络阅读我在docker中观察到的是虚拟图像大小.硬盘上的实际尺寸对我来说似乎很神秘,因为关于官方信息`docker ps -s`在硬盘上显示实际大小,在我的情况下是-1B.这听起来很合理,**减去1 Byte**.我在HDD上获得了一些空间......似乎合法. (10认同)
  • 感谢您为调查此案例所做的努力,是的,我能够将映像大小减少到大约 635MB(这是执行“docker images”后以虚拟映像大小显示的值)。是否可以删除/删除/销毁那些旧层?更具体地说:我想从历史记录中完全删除(根据您的示例)图像:172743bd5d60、3f2fed40e4b0、fd241224e9cf、511136ea3c5a,以便我的虚拟图像大小与最终图像大小大致相同,此处〜260MB 。 (2认同)

Tra*_*der 59

Docker图像不大,您只是构建大图像.

scratch如果您可以将代码编译为静态二进制文件,则图像为0B并且您可以使用它来打包代码.例如,您可以编译Go程序并将其打包在顶部,scratch以生成小于5MB的完全可用的图像.

关键是不要使用官方Docker镜像,它们太大了.Scratch也不是那么实用,因此我建议使用Alpine Linux作为基本映像.它大约是5MB,然后只添加你的应用程序所需的内容.这篇关于Microcontainers的文章向您展示了如何基于Alpine构建非常小的图像.

更新:官方Docker图像现在基于alpine,因此它们现在很好用.

  • 很好的解决方案!停止浪费并保持更安全非常重要 - >减少代码 - >减少担心. (2认同)
  • 值得庆幸的是,Docker 官方镜像也开始使用 Alpine 基础,因此您越来越多地可以使用常规镜像,而不是依赖iron.io 的版本。请参阅 https://www.brianchristner.io/docker-is-moving-to-alpine-linux/ (2认同)

Mun*_*kin 25

以下是您可以做的更多事情:

  • 尽可能避免使用多个RUN命令.尽可能多地放入一个RUN命令(使用&&)
  • 清理不必要的工具,如wget或git(你只需要下载或构建东西,但不要运行你的进程)

有了这两个和@Andy和@michau的推荐,我能够将我的nodejs图像从1.062 GB调整到542 MB.

编辑:还有一个重要的事情: "我花了一段时间才能真正了解每个Dockerfile命令创建与三角洲新的容器[...]这不,如果你RM -rf在后面的命令文件无关紧要.它们继续存在于某个中间层容器中." 所以,现在我设法把apt-get install,wget,npm install(用git的依赖),并apt-get remove成一个单一的RUN命令,所以现在我的形象只有438 MB.

编辑29/06/17

使用Docker v17.06,Dockerfiles提供了一些新功能:您可以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
Run Code Online (Sandbox Code Playgroud)

将导致一个图像只有nodejs基本图像加上来自/ var/my-project的内容 - 但没有 ruby,python,git,openssh和gcc!


mic*_*hau 20

是的,那些尺寸是荒谬的,我真的不知道为什么这么少人注意到这一点.

我制作了一个实际上最小的Ubuntu图像(与其他所谓的"最小"图像不同).它被称为textlab/ubuntu-essential60 MB.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano
Run Code Online (Sandbox Code Playgroud)

安装nano后,上图为82 MB.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano git
Run Code Online (Sandbox Code Playgroud)

Git有更多先决条件,因此图像变大,大约192 MB.这仍然是大多数图像的初始大小.

您还可以查看我编写的脚本,为Docker制作最小的Ubuntu映像.您可以将其改编为Fedora,但我不确定您能够卸载多少.


小智 13

以下帮助了我很多:

在我的容器内移除未使用的包(例如redis 1200 mb释放)之后,我做了以下操作:

  1. docker export [containerID] -o containername.tar
  2. docker import -m"在此处提交消息"containername.tar imagename:tag

层变平.新图像的大小会更小,因为我已经从容器中删除了包,如上所述.

这需要花费大量时间来理解这一点,这就是我添加评论的原因.


小智 7

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

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all
Run Code Online (Sandbox Code Playgroud)


jer*_*own 6

Docker Squash 是一个非常好的解决方案。您可以$packagemanager clean在最后一步而不是在每一行中,然后运行 ​​docker squash 来删除所有层。

https://github.com/jwilder/docker-squash