Golang在基于scratch的镜像中允许执行二进制的附加标志设置

Golang在基于scratch的镜像中允许执行二进制的附加标志设置 我正在构建一个简单的 go 应用程序,并希望最小化我的 docker 镜像大小。

我遵循了一篇在 Medium 上非常流行的文章的初始步骤。

于是我的初始 Dockerfile 变成了:

FROM golang:alpine AS builder
RUN apk update && apk add --no-cache git
WORKDIR $GOPATH/src/github.com/myrepo/mybot/
COPY . .
RUN go get -d -v
# Build the binary.
RUN go build -o /go/bin/mybot

FROM scratch
COPY --from=builder /go/bin/mybot /go/bin/mybot
ENTRYPOINT ["/go/bin/mybot"]

然而,当我尝试执行我的镜像时,我遇到了以下错误:

standard_init_linux.go:211: exec user process caused "no such file or directory"

当我将 go build 命令替换为以下内容时,问题得到了解决:

RUN CGO_ENABLED=0 go build -o /go/bin/workabot -a -ldflags '-extldflags "-static"' . 

为什么设置 CGO_ENABLED=0 以及设置标志 -a-ldflags '-extldflags "-static" 允许程序在 scratch 镜像上运行?


更多关于Golang在基于scratch的镜像中允许执行二进制的附加标志设置的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang在基于scratch的镜像中允许执行二进制的附加标志设置的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在基于 scratch 的 Docker 镜像中运行 Go 二进制文件时,需要确保二进制文件是完全静态链接的。默认情况下,Go 编译器可能生成依赖系统动态库的二进制文件,而 scratch 镜像不包含任何库文件。

以下是关键标志的作用:

  1. CGO_ENABLED=0:禁用 CGO,强制 Go 使用纯 Go 的实现,避免依赖 C 库。
  2. -a:强制重新编译所有依赖包,确保使用当前设置(如 CGO_ENABLED=0)重新构建。
  3. -ldflags '-extldflags "-static"':指示链接器使用静态链接,即使 CGO 被启用也会尝试静态链接 C 库。

示例代码

FROM golang:alpine AS builder
RUN apk update && apk add --no-cache git
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o myapp .

FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]

验证二进制文件是否为静态链接

# 在构建阶段检查二进制文件类型
ldd myapp
# 输出应为 "not a dynamic executable"

替代简化方案

FROM golang:alpine AS builder
WORKDIR /app
COPY . .
RUN go build -tags netgo -ldflags '-w -extldflags "-static"' -o myapp .

FROM scratch
COPY --from=builder /app/myapp /myapp
ENTRYPOINT ["/myapp"]

关键点

  • scratch 镜像不提供任何运行时依赖(包括 libc
  • 默认情况下,Go 的 net 包可能依赖系统 DNS 解析库
  • 使用 -tags netgo 可强制使用纯 Go 的 DNS 解析器

完整生产示例

# 构建阶段
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
    -a \
    -installsuffix cgo \
    -ldflags '-s -w -extldflags "-static"' \
    -o /app/myapp

# 运行阶段
FROM scratch
COPY --from=builder /app/myapp /myapp
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
ENTRYPOINT ["/myapp"]

此配置确保二进制文件在 scratch 镜像中独立运行,无需外部依赖。

回到顶部