5

I've the following docker file which is working for my application. I was able to access to the simple web app server.

FROM golang:1.14.7 AS builder
RUN go get github.com/go-delve/delve/cmd/dlv
RUN mkdir /app

ADD . /app
WORKDIR /app
RUN CGO_ENABLED=0 GOOS=linux go build -gcflags="all=-N -l" -o main ./...

FROM alpine:3.12.0 AS production
COPY --from=builder /app .
EXPOSE 8000 40000
ENV PORT=8000
CMD ["./main"]

When I adopt it like following, I am not able to deploy it successfully to Kubernetes. The container crashed with some general error, not something that I can use.

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

This not working

FROM golang:1.14.7 AS builder
RUN go get github.com/go-delve/delve/cmd/dlv
RUN mkdir /app

ADD . /app
WORKDIR /app
RUN CGO_ENABLED=0 GOOS=linux go build -gcflags="all=-N -l" -o main ./...

FROM alpine:3.12.0 AS production
COPY --from=builder /app .
COPY --from=builder /go/bin/dlv /
EXPOSE 8000 40000
ENV PORT=8000
CMD ["/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "./main"]

If someone want to try it out this is the simple program (this is minimum reproducible example), if you take the first docker file it will work for you, for the second it does not.

package main

import (
    "fmt"
    "net/http"
    "os"
)

func main() {
    fmt.Println("app is starting!")

    var port string
    if port = os.Getenv("PORT"); len(port) == 0 {
        port = "8080"
    }
    http.HandleFunc("/", handler)
    http.ListenAndServe(":"+port, nil)

}

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there,  %s!", r.URL.Path[1:])
}
David Medinets
  • 5,160
  • 3
  • 29
  • 42
PJEM
  • 557
  • 7
  • 33
  • Please show us the error as well. – shmsr Aug 14 '20 at 04:43
  • Try to build on an alpine based builder image like `golang:1.14.6-alpine3.12` – Henry Aug 14 '20 at 06:47
  • @Henry - I try it out and it doesnt work either, any other idea ? – PJEM Aug 14 '20 at 07:12
  • @shmsr - the error is : `standard_init_linux.go:190: exec user process caused "no such file or directory" ` – PJEM Aug 14 '20 at 07:12
  • Does this answer your question? [standard\_init\_linux.go:190: exec user process caused "exec format error" when running Go binary](https://stackoverflow.com/questions/55786898/standard-init-linux-go190-exec-user-process-caused-exec-format-error-when-ru) –  Aug 14 '20 at 07:23
  • @mh-cbon - thanks,i'll try it now however not sure how it works as the first docker file works and I dont change any of the go build command `arch` etc. – PJEM Aug 14 '20 at 07:33
  • @mh-cbon - I've added the `GOARCH=amd64` to the build command and the same error occurred.any other idea? – PJEM Aug 14 '20 at 07:39
  • maybe `RUN GOARCH=amd64 go get github.com/go-delve/delve/cmd/dlv` ? –  Aug 14 '20 at 08:02
  • something like this –  Aug 14 '20 at 08:03
  • alternatively why not using debian for all stages, or alpine. Avoid mixing those two imho. –  Aug 14 '20 at 08:06
  • @mh-cbon - im trying now you suggestion, add the arch to delve download and use `debian:buster` at final stage. – PJEM Aug 14 '20 at 09:01
  • @mh-cbon - Thank you very much! indeed, the change that you proposed to user `debian` does solve the problem, please write it as answer and i'll close the question. , now I see other issue as in the log is see `API server listening at: [::]:40000` and not my app logs, but i'll open another question, thank you very much!! – PJEM Aug 14 '20 at 09:17
  • fyi, it has something to do with the libc they use internally, but i am not much into C stuff so i dont expand too much about this; happy uou solved your problem –  Aug 14 '20 at 11:33
  • @mh-cbon - I see the answer below and voted, however please add your answer too as you help me to figure out the issue. thanks! – PJEM Aug 14 '20 at 14:47
  • that is kind from you. From my point of view i would rather like that you accept the best answer, from BMitch, as i have learned things aswel. –  Aug 14 '20 at 14:52
  • @mh-cbon - you are kind :) , great to know that there is people like you that are really want to help. thanks a lot, have a nice weekend ! – PJEM Aug 14 '20 at 15:13

1 Answers1

2

You need to compile dlv itself with the static linking flags. Without that, dlv will have dynamic links to libc which doesn't exist within an alpine image. Other options include switching your production image to be debian based (FROM debian) or change to golang image to be alpine based (FROM golang:1.14.7-alpine). To compile dlv without dynamic links, the following Dockerfile works:

FROM golang:1.14.7 AS builder
RUN CGO_ENABLED=0 go get -ldflags '-s -w -extldflags -static' github.com/go-delve/delve/cmd/dlv
RUN mkdir /app

ADD . /app
WORKDIR /app
RUN CGO_ENABLED=0 GOOS=linux go build -gcflags="all=-N -l" -o main ./...

FROM alpine:3.12.0 AS production
COPY --from=builder /app .
COPY --from=builder /go/bin/dlv /
EXPOSE 8000 40000
ENV PORT=8000
CMD ["/dlv", "--listen=:40000", "--headless=true", "--api-version=2", "--accept-multiclient", "exec", "./main"]    

To see the dynamic links, build your builder image and run ldd against the output binaries:

$ docker build --target builder -t test-63403272 .
[+] Building 4.6s (11/11) FINISHED                                                                                                                                                                                 
 => [internal] load build definition from Dockerfile                                                                                                                                                          0.0s
 => => transferring dockerfile: 570B                                                                                                                                                                          0.0s
 => [internal] load .dockerignore                                                                                                                                                                             0.0s
 => => transferring context: 2B                                                                                                                                                                               0.0s
 => [internal] load metadata for docker.io/library/golang:1.14.7                                                                                                                                              0.2s
 => [builder 1/6] FROM docker.io/library/golang:1.14.7@sha256:1364cfbbcd1a5f38bdf8c814f02ebbd2170c93933415480480104834341f283e                                                                                0.0s
 => [internal] load build context                                                                                                                                                                             0.0s
 => => transferring context: 591B                                                                                                                                                                             0.0s
 => CACHED [builder 2/6] RUN go get github.com/go-delve/delve/cmd/dlv                                                                                                                                         0.0s
 => CACHED [builder 3/6] RUN mkdir /app                                                                                                                                                                       0.0s
 => [builder 4/6] ADD . /app                                                                                                                                                                                  0.1s
 => [builder 5/6] WORKDIR /app                                                                                                                                                                                0.0s
 => [builder 6/6] RUN CGO_ENABLED=0 GOOS=linux go build -gcflags="all=-N -l" -o main ./...                                                                                                                    4.0s
 => exporting to image                                                                                                                                                                                        0.2s
 => => exporting layers                                                                                                                                                                                       0.2s
 => => writing image sha256:d2ca7bbc0bb6659d0623e1b8a3e1e87819d02d0c7f0a0762cffa02601799c35e                                                                                                                  0.0s
 => => naming to docker.io/library/test-63403272                                                                                                                                                              0.0s

$ docker run -it --rm test-63403272 ldd /go/bin/dlv
        linux-vdso.so.1 (0x00007ffda66ee000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007faa4824d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007faa4808c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007faa48274000)

Libc is a common missing library when switching to alpine since it uses musl by default.

BMitch
  • 231,797
  • 42
  • 475
  • 450