我有以下 Dockerfile
FROM golang as builder
ARG CADDY_HASH=4b4e99bdb2e327d553a5f773f827f624181714af
WORKDIR /root/caddy
RUN wget -qO- github.com/caddyserver/caddy/archive/"$CADDY_HASH".tar.gz | tar zx --strip-components=1
RUN set -e; cd cmd/caddy && CGO_ENABLED=0 go build
FROM scratch
COPY --from=builder /root/caddy/cmd/caddy/caddy /
ARG PORT=8000
ENV PORT $PORT
EXPOSE $PORT
CMD /caddy file-server --browse --listen :$PORT
我用这个命令构建和运行
DOCKER_BUILDKIT=0 docker build -t caddy-static-docker:latest . && docker run -e PORT=8000 -p 8000:8000 caddy-static-docker:latest
为什么这不起作用并且我收到此错误?
docker:来自守护进程的错误响应:未能创建 shim:OCI 运行时创建失败:container_linux.go:380:启动容器进程导致:exec:“/bin/sh”:stat /bin/sh:没有这样文件或目录:未知。
回答1
使用入口点而不是 CMD
ENTRYPOINT ["/caddy"]
CMD ["file-server", "--browse", "--listen", "8080"]
还要注意 json 语法(exec 形式),这会导致事情不在子 shell 中运行。
与 shell 形式不同,exec 形式不调用命令 shell。这意味着不会发生正常的外壳处理。例如,CMD [ "echo", "$HOME" ] 不会对 $HOME 进行变量替换。如果你想要 shell 处理,那么要么使用 shell 形式,要么直接执行 shell,例如:CMD [ "sh", "-c", "echo $HOME" ]。当使用 exec 形式并直接执行 shell 时,与 shell 形式一样,是 shell 进行环境变量扩展,而不是 docker。
来源:https://docs.docker.com/engine/reference/builder/#cmd
shell 形式阻止使用任何 CMD 或运行命令行参数,但缺点是您的 ENTRYPOINT 将作为 /bin/sh -c 的子命令启动,它不会传递信号。这意味着可执行文件将不是容器的 PID 1 - 并且不会接收 Unix 信号 - 因此您的可执行文件将不会收到来自 docker stop 的 SIGTERM。
来源:https://docs.docker.com/engine/reference/builder/#entrypoint
您的 PORT 仍会引起问题。考虑对其进行硬编码。
回答2
使用一个 alpine
图像,它是一个轻量级图像来运行 shell 命令,它已经加载了 /bin/sh
。
SCRATCH 映像基本上是空的,/
文件夹内没有任何内容,因此没有可执行文件来执行作为 CMD 的一部分提供的任何内容。