“用 alpine 镜像小”到底小多少?这篇把 busybox、alpine、debian-slim、ubuntu 拉下来,数文件、看 libc 和包管理器,再用同一个 Go 程序实际装进去,看镜像最后多大,以及最小的 scratch 要付出什么代价。
busybox:1.36 DISK USAGE 6.14MB CONTENT SIZE 1.9MB alpine:3.20 DISK USAGE 13.6MB CONTENT SIZE 4.09MB debian:12-slim DISK USAGE 136MB CONTENT SIZE 28.1MB ubuntu:24.04 DISK USAGE 139MB CONTENT SIZE 28.9MB
busybox:1.36 是 6.14MB,alpine:3.20 是 13.6MB,debian:12-slim 是 136MB,ubuntu:24.04 是 139MB(docker images 的 DISK USAGE)。压缩后的内容分别是 1.9、4.09、28.1、28.9 MB。这是 arm64 版本,amd64 版本大小可能不同(本文没有测)。
[busybox:1.36] 文件数 424 | libc: | shell: /bin/sh | 包管理器: dpkg [alpine:3.20] 文件数 89 | libc: /lib/ld-musl-aarch64.so.1 | shell: /bin/sh | 包管理器: apk | 系统: Alpine Linux v3.20 [debian:12-slim] 文件数 3266 | libc: /lib/aarch64-linux-gnu/libc.so.6 | shell: /bin/sh /bin/bash | 包管理器: apt-get dpkg | 系统: Debian GNU/Linux 12 (bookworm) [ubuntu:24.04] 文件数 2589 | libc: /lib/aarch64-linux-gnu/libc.so.6 | shell: /bin/sh /bin/bash | 包管理器: apt-get dpkg | 系统: Ubuntu 24.04.5 LTS
alpine 里只有 89 个文件,用 musl 和 apk;debian-slim 有 3266 个文件,用 glibc,带 bash、apt-get、dpkg;ubuntu 是 2589 个文件。选 alpine 还是 debian 不只是大小的问题:libc 不同,依赖 glibc 的预编译二进制在 alpine 里可能跑不起来(本文没有测这一点)。busybox 里 command -v dpkg 能找到,为什么我没有查。
Go 静态二进制(-ldflags="-s -w"):1.57 MB FROM scratch → 镜像 Size 2.22 MB;运行输出:hello from static go FROM busybox:1.36 → 镜像 Size 8.36 MB;运行输出:hello from static go FROM alpine:3.20 → 镜像 Size 15.80 MB;运行输出:hello from static go FROM debian:12-slim → 镜像 Size 138.15 MB;运行输出:hello from static go FROM ubuntu:24.04 → 镜像 Size 141.60 MB;运行输出:hello from static go
把 CGO_ENABLED=0 编译的 1.57 MB 静态 Go 程序分别 COPY 进五个 FROM,镜像大小是 2.22(scratch)、8.36(busybox)、15.80(alpine)、138.15(debian-slim)、141.60(ubuntu)MB。程序本身没变,基础镜像占了镜像体积的绝大部分。scratch 比二进制本身多出的 0.65 MB 我推测是压缩内容与解包层都被计入(docker image inspect 的 Size),没有单独验证。
scratch:退出码 127;输出:docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: exec: "sh": executable file not found in $PATH alpine:3.20:退出码 0;输出:shell 可用
scratch 里没有 shell:docker run --entrypoint sh 报 exec: "sh": executable file not found in $PATH,退出码 127;alpine 里同样的命令成功。需要进容器排查的服务,体积和可排查性要自己权衡。