为 Kubernetes 构建小型容器

2025-06-08

为 Kubernetes 构建小型容器

这是一篇转帖。原帖可以在我的博客上找到。

将任何应用部署到Kubernetes 的第一步,都是将应用打包到容器中。市面上有多个官方和社区支持的容器镜像,适用于各种语言和发行版,其中大多数容器可能非常庞大,有时甚至包含您的应用可能永远不需要/用不到的开销。

借助Docker,您只需几个步骤即可轻松创建容器映像;指定基础映像、添加特定于应用程序的更改并构建容器。

FROM golang:alpine

WORKDIR /app

ADD . /app

EXPOSE 8080

ENTRYPOINT ["/app/run"]
Enter fullscreen mode Exit fullscreen mode

我们指定了一个基础镜像(本例中为 Linux alpine),设置了容器中要使用的工作目录,公开了一个网络端口,以及一个用于在容器中启动应用程序的入口点。设置好 Dockerfile 后,我们就可以构建容器了。

$ docker build myapp .
Enter fullscreen mode Exit fullscreen mode

虽然上述过程非常简单,但仍有一些问题需要考虑。使用默认镜像可能会导致容器镜像过大、安全漏洞和内存开销。

让我们充实一个示例应用程序

我们将用 Go 编写一个简单的应用,它暴露一个 HTTP 路由,当路由命中时会返回一个字符串。我们将用它构建一个 Docker 镜像。

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func main() {
    r := http.NewServeMux()
    r.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello From Go!")
    })
    s := &http.Server{
        Addr:        ":8080",
        Handler:     r,
        ReadTimeout: 10 * time.Second,
    }
    fmt.Println("Starting server on port 8080")
    log.Fatal(s.ListenAndServe())
}
Enter fullscreen mode Exit fullscreen mode

让我们用我们的应用程序构建 Docker 镜像。首先,我们需要创建一个 Dockerfile。

FROM golang:latest

RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o myapp .

CMD ["/app/myapp"]
Enter fullscreen mode Exit fullscreen mode

构建图像。

PS:用任何选择的内容替换标签:/appname

$ docker build -t codehakase/goapp .
Enter fullscreen mode Exit fullscreen mode

就这样!我们刚刚 Docker 化了一个简单的 Go 应用。让我们来看看
刚刚构建的镜像。
Docker 镜像列表

对于一个简单的 Go 应用来说,镜像文件的大小就超过 700 MB。Go 二进制文件本身
可能只有几 MB,额外的开销不仅浪费了空间,
还可能成为 bug 和安全漏洞的藏身之处。

什么东西占用了这么多空间?在这种情况下,容器需要
安装 Go,以及 Go 所依赖的所有依赖项,所有这些都位于
Debian 或 Linux 发行版之上。

有两种方法可以减少容器镜像的大小,实际上有三种,其中
第三种在 Go 社区中更常用:

  1. 使用小型基础镜像
  2. 建造者模式
  3. 使用空图像

使用小型基础镜像是减少容器镜像大小最简单的方法。
所使用的堆栈/语言可能提供的官方镜像
比默认镜像小得多。


golang:alpine让我们更新 Dockerfile 以使用一个较小的基础镜像。在本例中我们将使用它。

FROM golang:alpine

RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN go build -o myapp .

CMD ["/app/myapp"]
Enter fullscreen mode Exit fullscreen mode

重建图像。

$ docker build -t codehakase/goapp .
Enter fullscreen mode Exit fullscreen mode

随着 Dockerfile 的更新,我们的镜像现在比
以前的镜像更小了。
使用小型基础图像

这个镜像大小仍然很大,我们可以使用
建造者模式将其缩小。由于我们在本例中使用了编译型语言(Go),因此在
建造者模式中,我们应该注意,编译型语言通常需要一些
并非运行代码所必需的工具。这些工具主要用于构建和编译为二进制文件。使用建造者模式,我们可以 在最终容器中
移除这些工具。

为了在我们现有的示例中使用 Builder 模式,我们将在
容器中编译我们的代码,然后使用编译后的代码打包最终的容器,而无需
所有必需的工具。

FROM golang:alpine AS main-env
RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN cd /app && go build -o myapp

FROM alpine
WORKDIR /app
COPY --from=main-env /app/myapp /app
EXPOSE 8080

ENTRYPOINT ./myapp
Enter fullscreen mode Exit fullscreen mode

我们更新了 Dockerfile 以使用构建器模式。首先,它在容器
中构建并编译应用程序alpine并命名为步骤main-env,然后
将上一步中的二进制文件复制到新容器中。

重建多阶段 Dockerfile。

$ docker build -t codehakase/goapp .
Enter fullscreen mode Exit fullscreen mode

构建的结果是一个刚好超过 10
兆字节的新容器。
建造者模式

还记得我们构建的第一个镜像超过 700 MB 吗?我们
使用构建器模式将其缩减到 10.7 MB。

我们仍然可以通过使用临时(空)
镜像来稍微减少这个数字。什么是临时镜像?它是一个特殊的空 Docker 镜像。要使用
它,我们需要首先在 Docker 环境之外构建我们的应用程序,并将编译后的二进制文件添加
到容器中。

$ go build -o myapp .
Enter fullscreen mode Exit fullscreen mode

我们将更新 Dockerfile 以将二进制文件添加到临时映像。

FROM scratch
ADD myapp /
CMD ["/myapp"]
Enter fullscreen mode Exit fullscreen mode

让我们构建这个图像并看看它有多大。
临时图像

我们把它压缩到了 6.5MB,太棒了!让我们尝试运行容器来测试
我们的应用。

$ docker run -it codehakase/goapp
Enter fullscreen mode Exit fullscreen mode

您可能会收到如下错误:

出现此错误的原因是,Go 二进制文件正在其运行的操作系统上寻找库
,由于临时映像为空,因此没有可供查找的库。
我们需要修改构建命令以静态编译我们的 Go 应用程序:

$ GO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
Enter fullscreen mode Exit fullscreen mode

使用重建docker build -t codehakase/goapp,并再次运行我们的容器
,将容器上的端口转发到我们的机器:

$ docker run -it -p 8080:8080 codehakase/goapp
  Starting server on port 8080
Enter fullscreen mode Exit fullscreen mode

导航至以http://localhost:8080/api测试应用程序的响应。

结论

本文旨在解释如何
专门针对 Go 应用缩减容器大小。容器越小,性能就越高,因为
在 CI 环境中构建容器的速度会更快,将
构建好的镜像推送到容器注册表所需的时间也会更少,
最重要的是,将这些容器拉取到分布式 Kubernetes
集群的速度也会更快,因为较小的容器不太可能延迟
新集群的部署。

如果您有任何建议或意见,请在下方留言或联系
@codehakase

鏂囩珷鏉ユ簮锛�https://dev.to/codehakase/building-small-containers-for-kubernetes-290j
PREV
机械键盘101
NEXT
22 个 YouTube 频道助你提升编程技能 什么是编程?它是如何运作的? 最有价值的计算机程序员技能是什么? 如何成为一名计算机程序员? 你的计算机编程简历(+ 工作机会) 最受欢迎的编程语言 提升编程技能的 YouTube 频道 结论