前言
去年我发表了文章 对 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
能这么小的原因了。
大致为:
Alpine
中删除了一些不影响系统运行的辅助性资源文件;- 使用
Musl
取代了Glibc
; - 使用了
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
等搭建一个内网镜像中心,能让容器镜像的上传下载更快捷方便。
参考
- [1] 对 Docker 基础镜像的思考,该不该选择 alpine : https://taoofcoding.tech/blogs/2022-08-18/shoule-we-use-alpine-in-docker-image
转载声明