1

I try to build the go app as follow, my main.go file is at cmd/app/main.go.

However, when I try running docker build --no-cache . and docker run <container_id>. It gives me exec ./bin/app: no such file or directory

I've already test that running go build -o ./bin/app ./cmd/app and ./bin/app is able to run correctly.

Here is my Dockerfile

# Build phase
FROM golang:1.20 AS builder

WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download && go mod verify

COPY . .
RUN go build -o ./bin/app ./cmd/app

# Production phase
FROM alpine:3.14

WORKDIR /app

COPY --from=builder /app/bin/app ./bin/app

ENTRYPOINT [ "./bin/app" ]

I tried to access into the container docker run -it -t fyno/server/multi /bin/sh

/app # cd bin
/app/bin # ls -la
total 11636
drwxr-xr-x    2 root     root          4096 Apr 12 05:04 .
drwxr-xr-x    1 root     root          4096 Apr 12 05:04 ..
-rwxr-xr-x    1 root     root      11904381 Apr 12 05:04 app
/app/bin # ./app
/bin/sh: ./app: not found
/app/bin # 

Thanks.

how to fix the problem?

vincent0426
  • 37
  • 1
  • 4
  • You set WORKDIR to `/app` but then try to call `./bin/app` so it's trying to run `/app/bin/app` which probably doesn't exist. https://docs.docker.com/engine/reference/builder/#workdir – Andy Ray Apr 12 '23 at 04:51
  • Hi Andy, can you provide me maybe where should I fix? is the entrypoint part? I've tried to set it to `ENTRYPOINT [ "/app/bin/app" ]` but then `exec /app/bin/app: no such file or directory`. Thank you! – vincent0426 Apr 12 '23 at 05:02
  • 1
    Run bash in the container and look at the filesystem to find the file you want to run, and use that in the entrypoint path – Andy Ray Apr 12 '23 at 05:11
  • @AndyRay, I've edited the post how I access the container, but it says not found. – vincent0426 Apr 12 '23 at 05:19
  • Maybe you’re somehow dynamically linked against something? Try `ldd bin/app`. – Ry- Apr 12 '23 at 05:41
  • Hi, I found that it can't read the .env file. However, I don't want to COPY .env file into the docker file but using --env-file in docker-compose. But it may still fail first, I can't find the solution. Thank you. – vincent0426 Apr 12 '23 at 06:33
  • 2
    How did you determine that an .env file was the cause? That’s an unusual error message to be caused by something like that. Did you try `ldd`? – Ry- Apr 12 '23 at 06:53
  • The second problem(_not found_) has to do with the dynamic linking as @Ry- already suggested. You may disable CGO when building. I tried to articulate an answer for all the 3 issues. This answer covers the subject as well: https://stackoverflow.com/questions/36279253/go-compiled-binary-wont-run-in-an-alpine-docker-container-on-ubuntu-host – Neo Anderson Apr 14 '23 at 21:28

1 Answers1

1

First, there are some problems with the paths, causing your no such file or directory error.
I wrote a minimal Dockerfile example and renamed the app binary which was causing confusion because it was located in an app directory in your example. I hope it makes more sense now.

Second, after fixing the paths inaccuracies in the Dockerfile, you run into a more subtle problem, when trying to run the go binary: not found, because the the golang builder image is using Debian GLIBC 2.31-13+deb11u5 2.31 while the runner image is using musl libc (x86_64) Version 1.2.2.

The easiest fix is to set CGO_ENABLED=0 when building. If you really want to use cgo to compile, find a builder and a runner images that are compatible in this regard.
Several alternatives and workarounds are provided for a similar question here.

Third, you also mentioned about the .env file in a comment so I also included in the MVP a simple read-display for an environment variable injected with docker run --env ....

.
├── cmd
│   └── main.go
├── Dockerfile
├── go.mod
└── go.sum

Dockerfile:

# Build phase
FROM golang:1.20 AS builder
# Next line is just for debug
RUN ldd --version
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download && go mod verify
COPY . .
WORKDIR /build/cmd
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o go-binary

# Production phase
FROM alpine:3.14
# Next line is just for debug
RUN ldd; exit 0
WORKDIR /app
COPY --from=builder /build/cmd/go-binary .
ENTRYPOINT [ "/app/go-binary"]

main.go:

package main

import (
    "os"
    "time"

    "github.com/rs/zerolog/log"
)

func main() {
    yourVar := os.Getenv("YOUR_VAR")
    for {
        time.Sleep(time.Second)
        log.Info().Msg(yourVar)
    }
}

Build and run:

docker build --no-cache -t stack-overflow-go-docker:v1.0 .
docker run --env YOUR_VAR=your-value stack-overflow-go-docker:v1.0
{"level":"info","time":"2023-04-14T21:12:37Z","message":"your-value"}
{"level":"info","time":"2023-04-14T21:12:38Z","message":"your-value"}
Neo Anderson
  • 5,957
  • 2
  • 12
  • 29