5 个减少 Docker 镜像大小的技巧





5.00/5 (4投票s)
5 个减少 Docker 镜像大小的技巧 Docker 镜像很快会达到 1 GB 或更大。 尽管千兆字节的价格正在下降,但保持 Docker 镜像轻量级将带来一些好处。 这篇文章将向您介绍 5 个技巧,帮助您减小 Docker 镜像大小,以及为什么关注它很重要。
Docker 镜像很快会达到 1 GB 或更大。 尽管千兆字节的价格正在下降,但保持 Docker 镜像轻量级将带来一些好处。 这篇文章将向您介绍 5 个技巧,帮助您减小 Docker 镜像大小,以及为什么关注它很重要。
为什么镜像大小如此重要?
减小 Docker 最终镜像的大小将最终导致
- 减少构建时间
- 减少磁盘使用量
- 减少下载时间
- 由于占用空间更小,安全性更高
- 更快的部署
什么是层?
要减小镜像大小,了解什么是层很重要。 每个 Docker 镜像都由多个中间镜像(层)组成,这些中间镜像构成了最终镜像。 这种层堆叠允许 Docker 在找到相似的指令时重用镜像。
每个 Dockerfile 指令在构建时都会创建一个层
FROM ubuntu # This base image is already composed of X layers (4 at the time of writing) MAINTAINER Florian Lopes # One layer RUN mkdir -p /some/dir # One layer RUN apt-get install -y curl # One layer

镜像层的概述
让我们构建这个镜像
$ docker build -t curl . [...] $ docker images curl REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE test latest 732afd2af5a9 About an hour ago 199.3 MB
要查看镜像的中间层,请键入以下命令
$ docker history curl IMAGE CREATED CREATED BY SIZE 732afd2af5a9 About an hour ago /bin/sh -c apt-get install -y curl 11.32 MB 912b76f3dd8e About an hour ago /bin/sh -c mkdir -p /some/dir 0 B 525804109d88 About an hour ago /bin/sh -c #(nop) MAINTAINER Florian Lopes 0 B c88b54fedc4f 9 days ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B 44802199e669 9 days ago /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/ 1.895 kB 74a2c71e6050 9 days ago /bin/sh -c set -xe && echo '#!/bin/sh' > /u 194.5 kB 140d9fb3c81c 9 days ago /bin/sh -c #(nop) ADD file:ed7184ebed5263e677 187.8 MB
您可以在下方看到,每个层都有一个大小和与之关联的命令来创建它。 从此 Dockerfile 构建的最终镜像包含 3 层以及所有 Ubuntu 镜像层。
虽然这可能有点难以理解,但这种结构非常重要,因为它允许 Docker 缓存层以使构建更快。 在构建镜像时,Docker 守护进程将检查中间镜像(由指令创建的层)是否已存在于其缓存中以重用它。 如果找不到中间层或已更改,Docker 守护进程将拉取或重建它。
如何减小镜像大小
正如我们刚刚看到的,层在最终镜像大小中起着重要作用。 要减小最终大小,我们必须专注于中间层。 尽管其中一些无法减小(尤其是您开始使用的那个),但我们可以使用一些技巧来帮助减小最终镜像大小。
尽可能将命令组合成 一个 指令(不要在多个 RUN 指令中执行多个安装)
安装软件包
单独的指令
为了说明这一点,让我们使用两个单独的 RUN 指令构建一个镜像,该指令安装 curl
和 mysql-client
软件包
FROM ubuntu:16.04 MAINTAINER Florian Lopes RUN apt-get update RUN apt-get install -y curl RUN apt-get install -y mysql-client
$ docker build -t tip1 . [...] $ docker images tip1 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE tip1 latest 7e9105c27586 3 minutes ago 248.4 MB
单个指令
现在,让我们将两个指令组合成一个
FROM ubuntu:16.04 MAINTAINER Florian Lopes RUN apt-get update && apt-get install -y curl mysql-client
让我们再次构建我们的镜像
$ docker build -t tip1 . [...] $ docker images tip1 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE tip1 latest 2886d17dc7f4 9 seconds ago 248 MB
尽管大小差异不是那么显著,但当安装多个软件包时,您可以获得更好的结果。
删除软件包
单独的指令
让我们看另一个有趣的例子,在其中我们在单独的指令中删除一个 临时 软件包
FROM ubuntu:16.04 MAINTAINER Florian Lopes RUN apt-get update && apt-get install -y curl && curl http://[...] RUN apt-get remove -y curl
您可以在这里看到,curl 软件包在安装后立即在单独的指令中被删除。 让我们看看最终的镜像大小
$ docker build -t tip2 . [...] $ docker images tip2 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE tip1 latest 632f4bf8667c 8 seconds ago 182.7 MB
单个指令
这次,让我们将这些指令组合成一行
FROM ubuntu:16.04 MAINTAINER Florian Lopes RUN apt-get update && apt-get install -y curl && curl http://[...] && apt-get remove -y curl
$ docker build -t tip3 . [...] $ docker images tip3 REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE tip1 latest bfea5f186684 11 seconds ago 182.1 MB
您可以看到镜像的大小略有减小。 同样,这里的差异不是很大,因为我们只删除一个软件包。
为什么会有差异?
正如我们之前看到的,Docker 守护进程为每个指令创建一个镜像来执行相关的命令。 在单独的指令示例中,所有这些镜像的叠加创建了最终的镜像。 由于这种策略,mysql-client 软件包仍然是最终镜像的一部分(实际上在第三层),尽管稍后被删除。

在单独的指令中删除软件包

在单个指令中删除软件包
安装软件包时,不要安装软件包建议 (–no-install-recommends)
RUN apt-get update apt-get install -y --no-install-recommends curl
如果可能,在 同一个 指令中删除不再需要的软件包或文件
软件包示例
RUN apt-get update && \ apt-get install -y --no-install-recommends curl && \ curl http://download.app.com/install.sh && \ .install.sh && apt-get remove -y curl
在此示例中, curl 软件包仅用于检索安装文件。 由于不再需要它,因此可以删除它(在 同一个 指令中)。
文件示例
<code>RUN wget ${APP_URL} -o /tmp/app/install.sh && \ ./tmp/app/install.sh && \ rm -rf /tmp/app/ && \ rm -rf /var/lib/apt/lists/*
从更小的基础镜像开始
您是否需要每个 Ubuntu(或其他基础镜像)软件包? 如果没有,您应该考虑从更小的基础镜像开始,例如 Alpine (),它可能会成为所有官方 Docker 镜像的基础镜像 (Jenkins, Maven)。 这种基础镜像的重量约为 5MB,而 Ubuntu 镜像的重量约为 188MB。 您可以在这里看到 Docker 基础镜像的绝佳比较:https://www.brianchristner.io/docker-image-base-os-size-comparison/。
检查 DockerHub 中的镜像
要轻松检查 DockerHub 镜像,您可以使用 MicroBadger 服务:https://microbadger.com/

MicroBadger – Ubuntu 层
简而言之
- 尽可能将命令组合成 一个 指令
- 不要安装软件包建议 (–no-install-recommends)
- 在 同一个 指令中删除不再需要的软件包或文件
- 在安装软件包后清理 apt-cache
- 从更小的基础镜像开始:Alpine
如果您太忙(或懒惰)而无法专注于减小镜像大小,您可以使用此工具:https://github.com/jwilder/docker-squash。
文章 5 个减少 Docker 镜像大小的技巧 首次出现在 Florian Lopes 的博客上。