英文:
Why file cannot be found after being copied to a container
问题
我有一个类似以下的Dockerfile:
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" ]
它只是从一个hello-world的go文件构建一个二进制文件。然而,当我尝试使用以下docker-compose设置运行这个容器时,它显示exec ./start.sh: no such file or directory
。
version: "3"
services:
hello:
restart: always
build:
context: .
dockerfile: Dockerfile
目录的结构如下:
❯ tree .
.
├── Dockerfile
├── docker-compose.yaml
├── go.mod
├── hello
├── init.go
└── start.sh
所以start.sh
应该通过COPY . .
行加载到builder
容器中,并且应该通过COPY --from=builder /app/start.sh /app/start.sh
传递给第二个容器。
为了提供背景,start.sh
的内容如下:
#!/bin/bash
_main() {
echo "start"
}
_main "$@"
我最困惑的部分是,如果我在Dockerfile中将其更改为CMD [ "ls", "-l" ]
,它实际上会打印出:
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
而且,如果我将其更改为ENTRYPOINT [ './hello-bin' ]
,二进制文件也会成功运行。我只是无法弄清楚为什么它说没有./start.sh
。
更新:受到@larsks的启发,我注意到如果我将./start.sh
的头部从#!/bin/bash
更改为#!/bin/sh
,它就神奇地工作了。我仍然困惑于这里的潜在问题是什么,如果我想保留bash头部,我应该如何修复Dockerfile?
英文:
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?
答案1
得分: 3
发生错误是因为您在start.sh
中使用了#!/bin/bash
。
Alpine Docker镜像默认没有安装bash。它使用Busybox shell。
您可以在容器中安装bash。请参考https://stackoverflow.com/questions/40944479/docker-how-to-use-bash-with-an-alpine-based-docker-image
或者,您可以根据您在问题评论中提到的,将#!/bin/bash
更改为#!/bin/sh
。
英文:
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 https://stackoverflow.com/questions/40944479/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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论