2

I tried to use scratch to build a small image. I turned off the CGO but still fail to read the file when the program runs. I have got the error: "open ./app/a.txt: no such file or directory". Is there other reasons that the program cannot read the file?

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: %s\n", n1, string(b1[:n1]))
}
func check(err error) {
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}
David Maze
  • 130,717
  • 29
  • 175
  • 215
hy c
  • 115
  • 1
  • 9
  • As the error says: the file or directory does not exist. Most likely, your code is not running from the directory you think it is. – Jonathan Hall Jun 29 '20 at 09:27
  • Have you copied "./app/a.txt" into your docker image? Just to confirm, can you do docker exec /bin/bash and see if the file is there in the directory? – Bhupinder Singh Narang Jun 29 '20 at 09:58
  • There are a bunch of problems. The first one is "why do you expect "./app/a.txt" to exist in a scratch image that has exactly two files in it? – Paul Becotte Jun 29 '20 at 17:36
  • Thanks, I fixed it by moving the text file outside of my source code, so the path can be found when I use env variable – hy c Jul 02 '20 at 09:08

2 Answers2

2

alpine does not provide glibc. alpine is that small because it uses a stripped down version of libstdc called musl.libc.org.

So we'll check statically linked dependencies using ldd command.

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

Check the linked static files, do they exist on that version of alpine? If the do not from, the binaries perspective, it did not find the file-- and will report File not found.

The following step depends on what binaries were missing, you can look it up on the internet on how to install them.

Add RUN apk add --no-cache libc6-compat to your Dockerfile to add libstdc in some Golang alpine image based Dockerfiles.

In you case the solution is to either

  • disable CGO : use CGO_ENABLED=0 while building
  • or add RUN apk add --no-cache libc6-compat to your Dockerfile
  • or do not use golang:alpine
frozenOne
  • 558
  • 2
  • 8
  • This is definitely a problem- but not the problem that the error message is pointing them to. – Paul Becotte Jun 29 '20 at 17:37
  • @frozenOne thank you for your information. my code in dockerfile is fine, but I made a mistake to include the text file inside of my source code, which I cannot read the path once the program got complied. – hy c Jul 02 '20 at 09:12
0

I made a mistake to compile the go program with the txt file the program would like to read. That's why the file path was not correct once the program compiled to binary exec. Just in case someone made the same mistake like me, here's is one of my solution. I solved the problem by moving the text file outside of my project and use env variable to point to the path i want.

I think package "osext" is another way to do it. Find the path to the executable

hy c
  • 115
  • 1
  • 9