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

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

前言

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

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

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

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

1、探究

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

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 发行版本中的执行文件,它全部都只是busyboxalias 而已。

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

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

  • 第四:没有 apt 与 systemd

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

但在 Alpine 中,apk 取代了 aptAlpine 同样没有使用 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 等搭建一个内网镜像中心,能让容器镜像的上传下载更快捷方便。

参考

转载声明

目录
相关文章
|
23天前
|
缓存 Linux 网络安全
docker的镜像无法下载如何解决?
【10月更文挑战第31天】docker的镜像无法下载如何解决?
896 29
|
2月前
|
缓存 监控 持续交付
|
19天前
|
存储 关系型数据库 Linux
【赵渝强老师】什么是Docker的镜像
Docker镜像是一个只读模板,包含应用程序及其运行所需的依赖环境。镜像采用分层文件系统,每次修改都会以读写层形式添加到原只读模板上。内核bootfs用于加载Linux内核,根镜像相当于操作系统,上方为应用层。镜像在物理存储上是一系列文件的集合,默认存储路径为“/var/lib/docker”。
|
25天前
|
存储 监控 Linux
docker构建镜像详解!!!
本文回顾了Docker的基本命令和管理技巧,包括容器和镜像的增删改查操作,容器的生命周期管理,以及如何通过端口映射和数据卷实现容器与宿主机之间的网络通信和数据持久化。文章还详细介绍了如何使用Docker部署一个简单的Web应用,并通过数据卷映射实现配置文件和日志的管理。最后,文章总结了如何制作自定义镜像,包括Nginx、Python3和CentOS镜像,以及如何制作私有云盘镜像。
109 2
|
26天前
|
关系型数据库 MySQL Docker
docker环境下mysql镜像启动后权限更改问题的解决
在Docker环境下运行MySQL容器时,权限问题是一个常见的困扰。通过正确设置目录和文件的权限,可以确保MySQL容器顺利启动并正常运行。本文提供了多种解决方案,包括在主机上设置正确的权限、使用Dockerfile和Docker Compose进行配置、在容器启动后手动更改权限以及使用 `init`脚本自动更改权限。根据实际情况选择合适的方法,可以有效解决MySQL容器启动后的权限问题。希望本文对您在Docker环境下运行MySQL容器有所帮助。
65 1
|
28天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
1月前
|
消息中间件 Linux RocketMQ
在Red Hat Enterprise Linux 9上使用Docker快速安装并部署
通过以上步骤,你可以在Red Hat Enterprise Linux 9上使用Docker快速安装并部署RocketMQ。这种方法不仅简化了安装过程,还提供了一个灵活的环境来管理和扩展消息队列系统。RocketMQ作为一款高性能的分布式消息系统,通过Docker可以实现快速部署和高效管理。
58 2
|
1月前
|
消息中间件 Linux RocketMQ
在Red Hat Enterprise Linux 9上使用Docker快速安装并部署
通过以上步骤,你可以在Red Hat Enterprise Linux 9上使用Docker快速安装并部署RocketMQ。这种方法不仅简化了安装过程,还提供了一个灵活的环境来管理和扩展消息队列系统。RocketMQ作为一款高性能的分布式消息系统,通过Docker可以实现快速部署和高效管理。
37 3
|
1月前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
59 1
|
2月前
|
关系型数据库 MySQL Linux
基于阿里云服务器Linux系统安装Docker完整图文教程(附部署开源项目)
基于阿里云服务器Linux系统安装Docker完整图文教程(附部署开源项目)
295 3