寻根究底,为什么 Docker 中的 Alpine Linux 镜像能这么小?

简介: 在这篇文章中,我以 Docker 中的 Alpine 与 Debian 镜像来详细对比它们的大小,及导致它们大小的原因。我们都知道,Debian 比 Ubuntu 更精简,这样对比会更有价值。

前言

去年我发表了文章 对 Docker 基础镜像的思考,该不该选择 alpine,其中对于 Alpine Linux 镜像如此之小的原因我解释为它使用了 musl 而不是 glibc。

有人发现并指出了我的这个错误,说 musl 与 glibc 的大小差别不足以造成如此大的差距,应该别有原因。

我一直记着这事,最近抽时间再次研究了下,确实如其所说,Alpine Linux 之所以这么小的原因,虽然 musl 是其中一个原因,但它是多种因素导致的。

在此我有必要表示歉意,同时我需要补充这篇文章,对于 Alpine Linux 之所以这么小,再解释的更清楚一些。

1、探究

在这篇文章中,我以 Docker 中的 Alpine 与 Debian 镜像来详细对比它们的大小,及导致它们大小的原因。我们都知道,Debian 比 Ubuntu 更精简,这样对比会更有价值。

1.1 镜像大小

通过 docker images ls 命令,可以查出这两个镜像当前的 latest 版本的大小对比:

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
debian       latest    5c8936e57a38   3 weeks ago   124MB
alpine       latest    042a816809aa   3 weeks ago   7.05MB

其中 debian 的大小为 124M,而 alpine 的大小只有 7.05MB 左右,大小相差还是非常明显的。

接下来,我将探究为它们究竟差别在哪?

1.2 探究方法

通过 du -s * | sort -nr 计算文件夹大小,不断寻找两个镜像中的大小差别比较明显的一些关键目录。

1.3 结果

与大小有关的关键目录如下:(仅列出差别明显的关键目录)

  • Debian
36M   /usr/lib/x86_64-linux-gnu
31M   /usr/share/locale
13M   /usr/share/doc
8.2M  /lib/x86_64-linux-gnu
6.1M  /var
5.2M  /bin
4.0M  /sbin
  • Alpine
828.0K /bin
72.0K /var

2. 分析

通过上述目录,可以大致分析出, Alpine镜像能如此之小的原因大致能区分为几大类:

  • 第一:删除部分非必须的资源文件

可以看出,这两个目录在Alpine中压根没有

• /usr/share/locale: 国际化文件
• /usr/share/doc: 帮助文档

可以推断,Alpine 删除了类似的无用的资源文件,没有它们并不影响系统的运行。

  • 第二:使用 musl,而非 glibc

/usr/lib/x86_64-linux-gnu 与 /lib/x86_64-linux-gnu 这两个目录大多是 glibc,libc,perl 等的共享类库所有目录。如我在以前的文章中所述,Alpine 中没有使用 glibc,而是使用了 musl,所以这一部分占据的大小也小了很多。

同时,通过在 musl官网与 glibc 官网查阅它们的压缩安装包大小分别是:

  • musl
1.1MB musl-1.2.3.tar.gz
  • glibc
18M  glibc-2.3.6.tar.gz
123K glibc-libidn-2.3.6.tar.gz
320K glibc-linuxthreads-2.3.6.tar.gz
1.8M glibc-ports-2.16.0.tar.gz

可以看出,光是安装包就有20倍左右的差别,安装后当然相差更大。

  • 第三:使用了 busybox 工具集

同样,分析上面的目录,会发现一个有趣的现象,Debian 中的 /bin 与 /sbin 目录大小明显高于 Alpine 的 /bin,这又是为什么呢?

这是因为,Apline 使用的是 busybox 这个工具集。那 busybox 是什么呢?

你可以把 busybox 理解为 bin 命令的瑞士军刀。

我们都知道,Linux 中我们依赖各种命令去操作系统,比如 cd,ls,pwd 等,这些命令每个都是一个个可执行文件。

而 busybox 也是一个可执行文件,但它与众不同,它是包含了常用的 300 多个命令的工具集。

看代码更容易理解:

# 功能与ls类似
busybox ls
# 功能与pwd类似
busybox pwd
# 功能与kill类似
busybox kill

现在你明白了吗,Apline 中压根没有 ls,pwd 这些类似其它 Linux 发行版本中的执行文件,它全部都只是busybox 的 alias 而已。

也就是,Alpine 中最主要的一个命令文件,就是 busybox ,而 busybox 是一个 5M 不到大小的,包含近 300 多个命令的工具集。

是不是 bin 命令的瑞士军刀?

  • 第四:没有 apt 与 systemd

在 Debian/Ubuntu 中,包管理是 apt。同样,Debian 与大都数 Linux 类似,都是使用的 systemd。

但在 Alpine 中,apk 取代了 apt,Alpine 同样没有使用 systemd,而是使用了 OpenRC,无论是 apt 还是 OpenRC,都是轻而小的实现。

3. 结论

现在,我能比上一次稍微准确的说出 Alpine 能这么小的原因了。

大致为:

  1. Alpine 中删除了一些不影响系统运行的辅助性资源文件;
  2. 使用 Musl取代了 Glibc;
  3. 使用了 BusyBox, apt 以及 OpenRC等一些轻量级实现;

从这些做法上也能看出,Alpine 的定位不是普通的 Linux 系统,它应该是为嵌入式 Linux 而生,几 MB 的系统大小,当然更适合嵌入式 Linux。

这也从另一个角度充分说明 Linux 系统的优秀,也就是只需要一个 Linux 内核,其它外围的一切几乎都是可以替代的,而仍然能保证 Linux 系统的运行与一致性。

幸运的是,Linux 内核是开源的。而正因为它是开源的,今天 Linux 才能造福世界。

关于基础镜像是否使用 Alpine Linux 构建的建议

  • 如果你的服务,不依赖C,那 alpine 是合适的选择,否则不应当使用 alpine 做为基础镜像;
  • 考虑到部署的一致性,就算是容器,使用同一系的 Linux基础镜像是更妥当的选择,比如全是 Debian 系或 RHEL 系等;
  • 优化镜像的空间非常有必要,各种建议仍然非常有价值,但不要走的太过,镜像的空间问题并没有你想像的那么严重;
  • 在公司或项目级别,不要使用 Docker Hub 或其它公有云镜像,使用简易的 registry 或企业级 Harbor,Nexus 等搭建一个内网镜像中心,能让容器镜像的上传下载更快捷方便。

参考

转载声明

目录
相关文章
|
JavaScript Docker 容器
使用Docker多阶段构建优化镜像大小
使用Docker多阶段构建优化镜像大小
638 100
|
缓存 安全 Linux
优化Docker镜像大小的多阶段构建实践
优化Docker镜像大小的多阶段构建实践
664 99
|
缓存 Docker 容器
优化Docker镜像大小的五个实用技巧
优化Docker镜像大小的五个实用技巧
1029 98
|
安全 Go Docker
使用Docker多阶段构建优化镜像大小
使用Docker多阶段构建优化镜像大小
|
Ubuntu Linux 数据安全/隐私保护
Beta 版 Ubuntu 24.04 LTS 镜像开放下载:GNOME 46 + Linux 6.8
IT之家附上镜像下载地址:Beta 版 Ubuntu 24.04 LTS
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
1096 6
|
Docker 容器 应用服务中间件
Docker 客户端是如何拉取镜像的?
Docker客户端拉取镜像的过程遵循Docker Registry HTTP API V2规范,主要分为解析镜像名、鉴权、获取Manifest、拉取Layers及本地合并五个步骤。它与Docker Hub、Harbor等仓库通信,确保镜像正确下载和构建。
1917 59
|
缓存 Shell 网络安全
将应用程序打包成Docker镜像时可能遇到哪些问题?
将应用程序打包成Docker镜像时可能遇到哪些问题?
1366 77
|
缓存 Ubuntu Docker
Ubuntu环境下删除Docker镜像与容器、配置静态IP地址教程。
如果遇见问题或者想回滚改动, 可以重启系统.
769 16
|
Java Docker 容器
使用Docker多阶段构建优化镜像大小
使用Docker多阶段构建优化镜像大小
490 8