寻根究底,为什么 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 等搭建一个内网镜像中心,能让容器镜像的上传下载更快捷方便。

参考

转载声明

目录
相关文章
|
6月前
|
Docker 容器 Perl
云效flow构建docker镜像更换apt源为阿里镜像源
在 Dockerfile 中添加命令以更换 Debian 源为阿里云镜像,加速容器内软件包下载。核心命令通过 `sed` 实现源地址替换,并更新 apt 软件源。其中 `cat` 命令用于验证替换是否成功,实际使用中可删除该行。
1224 32
|
5月前
|
缓存 Shell 网络安全
将应用程序打包成Docker镜像时可能遇到哪些问题?
将应用程序打包成Docker镜像时可能遇到哪些问题?
466 77
|
5月前
|
人工智能 安全 Linux
Alpine Linux设定指定的软件包安装源
以上就是如何为Alpine Linux设置特定的软件包的安装源的全部流程。这个过程非常简洁、明了,希望你在使用过程中能够找到乐趣。这个过程不仅可以提供你需要的软件,还可以根据你的网络条件和地域性需求进行调整,使你的Alpine Linux系统达到最佳性能。
537 24
|
7月前
|
存储 JSON 数据格式
docker load 后镜像名称为空的问题解决
Docker在容器化应用程序时提供了强大的镜像管理功能,但也可能在某些操作中遇到如镜像名称为空的问题。通过理解问题的成因并采取适当的解决方案,如正确保存和加载镜像、手动修复标签等,可以有效避免和解决这一问题。通过本文提供的指导,您可以确保在使用Docker进行镜像操作时更为顺利,并提高容器管理的效率。
440 82
|
4月前
|
Linux iOS开发 Docker
MyEMS开源系统安装之Linux/macOS上的DOcker
本指南详细介绍了如何在Linux/macOS上使用Docker部署MyEMS系统。主要内容包括:前置条件(如安装Docker、npm和MySQL),以及分步骤部署各个组件(如myems-api、myems-admin、myems-modbus-tcp等)。每个步骤涵盖源代码复制、环境配置、镜像构建、容器运行及日志管理等操作,并提供了多平台构建的支持。最后,指南还说明了默认端口和登录凭据,帮助用户快速启动并访问MyEMS的管理界面和Web界面。
127 1
|
5月前
|
Shell 应用服务中间件 nginx
docker 镜像的部分常用命令
docker镜像常用命令
165 16
|
5月前
|
关系型数据库 MySQL Docker
|
6月前
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
277 28