赞
踩
公众号关注 「奇妙的 Linux 世界」
设为「星标」,每天带你玩转 Linux !
本系列文章将分为三个部分:
第一部分着重介绍多阶段构建(multi-stage builds),因为这是镜像精简之路至关重要的一环。在这部分内容中,我会解释静态链接和动态链接的区别,它们对镜像带来的影响,以及如何避免那些不好的影响。中间会穿插一部分对 Alpine
镜像的介绍。链接:两个奇技淫巧,将 Docker 镜像体积减小 99%[1]
第二部分将会针对不同的语言来选择适当的精简策略,其中主要讨论 Go
,同时也涉及到了 Java
,Node
,Python
,Ruby
和 Rust
。这一部分也会详细介绍 Alpine 镜像的避坑指南。什么?你不知道 Alpine
镜像有哪些坑?我来告诉你。
第三部分将会探讨适用于大多数语言和框架的通用精简策略,例如使用常见的基础镜像、提取可执行文件和减小每一层的体积。同时还会介绍一些更加奇特或激进的工具,例如 Bazel
,Distroless
,DockerSlim
和 UPX
,虽然这些工具在某些特定场景下能带来奇效,但大多情况下会起到反作用。
本文介绍第二部分。
Go
语言程序编译时会将所有必须的依赖编译到二进制文件中,但也不能完全肯定它使用的是静态链接,因为 Go
的某些包是依赖系统标准库的,例如使用到 DNS 解析的包。只要代码中导入了这些包,编译的二进制文件就需要调用到某些系统库,为了这个需求,Go 实现了一种机制叫 cgo
,以允许 Go 调用 C 代码,这样编译好的二进制文件就可以调用系统库。
也就是说,如果 Go 程序使用了 net
包,就会生成一个动态的二进制文件,如果想让镜像能够正常工作,必须将需要的库文件复制到镜像中,或者直接使用 busybox:glibc
镜像。
当然,你也可以禁止 cgo
,这样 Go 就不会使用系统库,使用内置的实现来替代系统库(例如使用内置的 DNS 解析器),这种情况下生成的二进制文件就是静态的。可以通过设置环境变量 CGO_ENABLED=0
来禁用 cgo,例如:
- FROM golang
- COPY whatsmyip.go .
- ENV CGO_ENABLED=0
- RUN go build whatsmyip.go
-
- FROM scratch
- COPY --from=0 /go/whatsmyip .
- CMD ["./whatsmyip"]
由于编译生成的是静态二进制文件,因此可以直接跑在 scratch
镜像中 本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/480853
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。