【问题标题】:How can I reduce the size of Docker images如何减小 Docker 映像的大小
【发布时间】:2017-04-26 12:22:46
【问题描述】:

我有 Node.js 应用程序,我作为 docker 容器运行。这是 该应用程序的 Dockerfile。

FROM ubuntu

ARG ENVIRONMENT
ARG PORT

RUN apt-get update -qq
RUN apt-get install -y build-essential nodejs npm nodejs-legacy vim

RUN mkdir /consumer_portal
ADD . /consumer_portal
WORKDIR /consumer_portal

RUN npm install -g express
RUN npm install -g path
RUN npm cache clean
RUN npm install

EXPOSE $PORT

ENTRYPOINT [ "node",  "server.js" ]
CMD [ $PORT, $ENVIRONMENT ]

我可以在这个 Dockerfile 中修改一些东西来减小 docker 镜像的大小

【问题讨论】:

  • 不安装vim?构建外部图像?
  • 使用 Alpine 基础镜像
  • @Aurélien anapsix/alpine-java 就是你所说的:我可以用什么代替 java 来代替节点
  • Alpine 是一个最小的 Linux 发行版。 hub.docker.com/r/mhart/alpine-node 例如
  • 我发现这非常有用:learnk8s.io/blog/smaller-docker-images 这篇文章中的示例也是针对 nodejs 图像的

标签: docker docker-compose dockerfile


【解决方案1】:

使用the official node alpine image 作为基础图像,正如这里大多数人所建议的那样,是减小图像整体大小的简单解决方案,因为即使是基础 alpine 图像也比基础 ubuntu 图像小很多。

Dockerfile 可能如下所示:

FROM node:alpine

ARG ENVIRONMENT
ARG PORT

RUN mkdir /consumer_portal \
    && npm install -g express path

COPY . /consumer_portal
WORKDIR /consumer_portal

RUN npm cache clean \
    && npm install

EXPOSE $PORT

CMD [ "node",  "server.js" ]

几乎相同,应该可以按预期工作。您的 ubuntu 映像中的大多数命令都可以以相同的方式应用到 alpine 映像中。

当我添加模拟数据以创建与您可能拥有的类似项目时,会生成一个大小为 491 MB 的 ubuntu 图像,而 alpine 版本只有 62.5 MB 大:

REPOSITORY   TAG       IMAGE ID        CREATED          SIZE
alpinefoo    latest    8ca6f338475e    5 minutes ago    62.5MB
ubuntufoo    latest    38620a1bd5a6    6 minutes ago    491MB

【讨论】:

  • 只有当对图像大小的主要贡献是基础层时,这才是正确的(例如,数据科学家发现情况通常并非如此)
【解决方案2】:

尽量将所有RUN指令打包在一起,这样会减少中间图像的数量。 (但它不会减小尺寸)。

apt-get update 之后添加rm -rf /var/lib/apt/lists/* 将通过删除所有无用的apt-get 内容来减小图像大小。

您还可以在最后一条 RUN 指令中从您的图像中删除 vim

FROM ubuntu

ARG ENVIRONMENT
ARG PORT

RUN apt-get update \
    && apt-get install -y build-essential nodejs npm nodejs-legacy vim \
    && rm -rf /var/lib/apt/lists/* \
    && mkdir /consumer_portal

ADD . /consumer_portal
WORKDIR /consumer_portal

RUN npm install -g express \
    && npm install -g path \
    && npm cache clean \
    && npm install

EXPOSE $PORT

ENTRYPOINT [ "node",  "server.js" ]
CMD [ $PORT, $ENVIRONMENT ]

【讨论】:

  • 感谢您的回答,但对我没有用,只有几 MB 减少了。
  • 如果你想使用 Ubuntu 作为基础镜像,你将无法减少更多的 MB。也许您应该考虑将基本映像更改为 Alpine 或类似的东西。
  • @JoséAntonioLópez 不知道高山,但请随时编辑我的帖子以改进答案;)
  • @AnandDeshmukh 要大幅减小图像大小,您无能为力(从 ubunto 切换到其他东西除外)。
  • 另一种选择是使用轻量级基础容器,例如 Alpine linux
【解决方案3】:

1) 搬到 Alpine 可能是最好的选择。我刚刚将一个 Ubuntu docker 文件移植到 Alpine,然后从 1.5GB 变为 585MB。我关注了these instructions。请注意,您将使用 apk 而不是 apt-get 并且 Alpine 包名称有点不同。

2)还可以通过合并运行命令来减少层数(每个新的运行命令都会创建一个新层)。

RUN apt-get update -qq && apt-get install -y build-essential nodejs npm nodejs-legacy vim
RUN npm install -g express path && npm cache clean && npm install

3) 您可能还对multi-stage build 感兴趣,其中您只将必要的组件复制到最终图像中。

【讨论】:

    【解决方案4】:

    考虑使用这个: 考虑在apt-get 安装软件包时使用--no-install-recommends。这将导致更小的图像尺寸。有关详细信息,请参阅此博客文章

    有一个很好的博客告诉你减少图像大小的几个步骤。

    减少 Docker 映像大小的技巧 https://hackernoon.com/tips-to-reduce-docker-image-sizes-876095da3b34

    【讨论】:

      【解决方案5】:

      第一步生成的图片,别名:builder

      将第一步图像的乘积复制到当前图像,只使用一个图像层,节省上一步的图像层数。

      FROM node:10-alpine as builder
      WORKDIR /web-console 
      ADD . /web-console
      RUN npm install
      RUN npm run build 
      
      FROM node:10-alpine
      WORKDIR /web-console
      COPY --from=builder . /web-console
      CMD ["npm", "run", "docker-start"]
      

      这里是一个带有 Maven 的 Java 示例:2 个步骤

      FROM maven:3.5.2-jdk-8-alpine as BUILD
      WORKDIR /app
      COPY pom.xml /app/
      COPY src /app/src/
      RUN mvn clean package -DskipTests
      
      FROM alpine
      WORKDIR /app
      COPY --from=BUILD /app/target/*.jar  application.jar
      ENTRYPOINT ["java", "-jar", "/application.jar"]
      

      【讨论】:

        【解决方案6】:

        如果您基于 Ubuntu,那么明智的做法就是这样做

        RUN apt-get update && apt-get install -y \
            build-essential \
            cwhatever-you-want \
            vim \
         && rm -rf /var/lib/apt/lists/*
        

        最后一行会清楚很多:) 您应该始终在同一行中进行 apt-get update,否则如果您添加另一个要安装的库,它将被缓存并且不会在下次构建时触发。

        【讨论】:

        • 是的。我基于 Ubuntu
        • 你能用我的 Dockerfile 纠正我吗?我应该把你提供的代码放在哪里
        • 当我在 Docekrfile 的第一行尝试 FROM mhart/alpine-node:base-6 时,我安装了 ubuntu 我的 docker 图像本身没有构建
        • Alpine,略有不同,见wiki.alpinelinux.org/wiki/…
        • Anthony 向您展示了我的示例帖子...不会再次复制粘贴它,因为它会是相同的 :)
        【解决方案7】:

        容器的图像大小是一个应该正确解决的问题。

        有些人建议使用 alpine 发行版来节省空间。

        原则上这是一个很好的建议,因为 alpine 有一个 nodejs 图像可供使用。

        但是你必须在这里小心,因为你必须构建所有的二进制文件。甚至 node_modules 通常只包含 javascript 包,在某些情况下,您需要构建二进制文件。

        如果您的 dockerfile 现在可以正常工作,那么这不应该是您的情况,但是当您从 ubuntu 迁移到不同类型的图像时,最好记住所有二进制文件你以后需要使用的必须编译成一个alpine镜像。

        说你应该在选择剪裁位置之前考虑如何使用你的图像。

        您的应用程序是单独存在于自己的容器中而没有任何其他节点应用程序的单个应用程序吗?

        如果答案是否定的,您应该知道本地 docker 注册表中每个图像的大小不计入汇总以获取总使用大小。

        相反,您必须在基本层中拆分每个图像并对每个 uniq 层求和。

        我的意思是,如果您有许多在一个节点上运行的节点应用程序,那么单个图像就不是那么重要了。

        您可以通过共享 node_modules 将其导出为包含所有所需依赖项的卷来节省空间。

        或者更好的是,您可以从官方的 nodejs 映像开始创建一个包含应用程序依赖根的中间映像。例如 expressjspath。然后在每个应用程序镜像中安装专用的依赖项。

        因此,您获得了共享层的优势,从而减少了本地 docker 注册表的总使用大小。

        次要注意事项

        您不需要在容器映像中全局安装 expresspath

        你真的需要 vim 在容器中吗? 考虑到即使在开发中修改容器也不安全。您可以使用卷来指向服务器文件系统上的资源。 或者在运行时从容器中复制入/出文件或文件夹。 如果您只是需要阅读某些内容,只需使用 less、more 或 cat 之类的命令。

        【讨论】:

          猜你喜欢
          • 2020-12-27
          • 2021-12-04
          • 1970-01-01
          • 2016-06-14
          • 1970-01-01
          • 1970-01-01
          • 2018-02-15
          • 1970-01-01
          • 2016-09-24
          相关资源
          最近更新 更多