0

I have a dockerfile like the following:

FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -v -o "hello-bin"


#FROM scratch
FROM alpine
COPY --from=builder /app/hello-bin /app/hello-bin
COPY --from=builder /app/start.sh /app/start.sh
WORKDIR /app
ENTRYPOINT  [ "./start.sh" ]

which simply build a binary from a hello-world go file. However, when I try to run this container with the following docker-compose setting, it showed exec ./start.sh: no such file or directory.

version: "3"

services:
  hello:
    restart: always
    build:
      context: .
      dockerfile: Dockerfile

The structure of the directory is

❯ tree .
.
├── Dockerfile
├── docker-compose.yaml
├── go.mod
├── hello
├── init.go
└── start.sh

So the start.sh should be loaded to the builder container via the COPY . . line as well, and it should be passed to the second container via the COPY --from=builder /app/start.sh /app/start.sh.

For context, the content of start.sh is as follows:

#!/bin/bash

_main() {
  echo "start"
}

_main "$@"

My most confusing part is that, if I change it to CMD [ "ls", "-l" ] in the Dockerfile, it actually prints out

awesomeproject3-hello-1  | -rwxr-xr-x    1 root     root       1819562 May 19 02:41 hello-bin
awesomeproject3-hello-1  | -rwxrwxrwx    1 root     root            51 May 19 02:39 start.sh

and also if I change it to ENTRYPOINT [ './hello-bin' ] in the Dockerfile, the binary runs successfully as well. I just can't figure out why it says there's no ./start.sh.


UPDATE: inspired by @larsks, I noticed if I change the header of ./start.sh from #!/bin/bash to #!/bin/sh, it magically worked. I am still confused what the underlying issue here, and if I want to keep the bash header, how should I fix the docker file?

IsaIkari
  • 1,002
  • 16
  • 31
  • What are the permissions on `start.sh`? What are the contents of `start.sh`? In particular, what does the `#!` line look like? If you inspect the image filesystem, do you see the files in `/app` as expected? – larsks May 19 '23 at 03:02
  • @larsks Thanks for responding -- 1. permission for `start.sh` is `-rwxrwxrwx`, as has been shown after I change it to `CMD [ "ls", "-l" ]` in the dockerfile; 2. the content of start.sh is just simply a `echo hello` with the `#!/bin/bash` header; 4. I believe `CMD [ "ls", "-l" ]` already showed the files in `/app` – IsaIkari May 19 '23 at 03:10
  • @larsks oh but I just tried changing the header to `#!/bin/sh`, it magically worked! But I'm still confused why?? The error message `exec ./start.sh: no such file or directory` is very misleading as it seems to say that the file doesn't exist at all! Also, if I want to keep the bash header, how should I fix the dockerfile? (updating the question body as well) – IsaIkari May 19 '23 at 03:13

1 Answers1

3

The error happening because you have used #!/bin/bash in your start.sh.

Alpine docker image doesn't have bash installed by default. It uses the Busybox shell instead.

you can install bash in your container. See Docker: How to use bash with an Alpine based docker image?

or you can change #!/bin/bash into #!/bin/sh as you noted in your comment on the question.

larsks
  • 277,717
  • 41
  • 399
  • 399
PRATHEESH PC
  • 1,461
  • 1
  • 3
  • 15
  • Thank you so much for saving my life! Adding `RUN apk add --no-cache bash` to the docker file fixed it. Though I think the `exec ./start.sh: no such file or directory` error is very misleading ... – IsaIkari May 19 '23 at 03:17
  • 1
    The script you show doesn't use any non-standard features and I would change the shebang line to `#!/bin/sh` (not `ash`, and you won't need to `apk install` anything). – David Maze May 19 '23 at 10:47