从头开始构建小映像(打开:没有这样的文件或目录)



我尝试使用scratch来构建一个小图像。我关闭了CGO,但在程序运行时仍然无法读取文件。我收到错误:"打开./app/a.txt:没有这样的文件或目录"。程序无法读取文件的其他原因是什么?

FROM golang:alpine AS builder
RUN apk update && apk add --no-cache git
WORKDIR $GOPATH/src/scratch
ADD . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -tags netgo -ldflags '-w -extldflags "-static"' -o /go/bin/scratch
FROM scratch
# Copy static executable.
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /go/bin/scratch /go/bin/scratch
# Run the binary.
ENTRYPOINT ["/go/bin/scratch"]
func main() {
resp, err := http.Get("https://google.com")
check(err)
body, err := ioutil.ReadAll(resp.Body)
check(err)
fmt.Println(len(body))
LocalFile := "./app/a.txt"
fmt.Println(LocalFile)
dat, err := ioutil.ReadFile(LocalFile)
check(err)
fmt.Print(string(dat))
f, err := os.Open(LocalFile)
check(err)
b1 := make([]byte, 5)
n1, err := f.Read(b1)
check(err)
fmt.Printf("%d bytes: %sn", n1, string(b1[:n1]))
}
func check(err error) {
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
alpine

不提供glibcalpine之所以这么小,是因为它使用了一个名为 musl.libc.org 的libstdc的精简版本。

因此,我们将使用ldd命令检查静态链接的依赖项。

$ docker run -it <image name> /bin/sh
$ cd /go/bin
$ ldd scratch   # or the excutable you are calling-> ldd <executable>

检查链接的静态文件,它们是否存在于该版本的 alpine 上?如果不从二进制文件的角度看,它没有找到文件,并将报告File not found

以下步骤取决于缺少的二进制文件,您可以在互联网上查找有关如何安装它们的文件。

RUN apk add --no-cache libc6-compat添加到您的 Dockerfile 以在某些基于Golang高山图像的 Dockerfile 中添加libstdc

在您的情况下,解决方案是

  • 禁用 CGO:在构建时使用CGO_ENABLED=0
  • 或添加RUN apk add --no-cache libc6-compat到您的Dockerfile
  • 或者不要使用golang:alpine

我犯了一个错误,用程序想要读取的txt文件编译go程序。这就是为什么一旦程序编译为二进制可执行文件,文件路径就不正确的原因。 以防万一有人像我一样犯了同样的错误,这是我的解决方案之一。 我通过将文本文件移动到我的项目之外并使用 env 变量指向我想要的路径来解决问题。

我认为包"osext"是另一种方法。 查找可执行文件的路径

最新更新