4

我将首先介绍 Heroku 文档中有关其容器注册表和 Docker 部署运行时的相关部分。

Docker 命令和运行时部分指出:

  • ENTRYPOINT是可选的。如果不设置,/bin/sh -c将使用
    • CMD将始终由 shell 执行,以便您的进程可以使用配置变量;要执行单个二进制文件或使用没有 shell 的图像,请使用ENTRYPOINT

我想强调最后一句话(强调):

要执行单个二进制文件或使用没有 shell 的图像,请使用ENTRYPOINT

此外,在不支持的Dockerfile 命令部分。

  • SHELL- Docker 镜像的默认 shell 是,您可以根据需要/bin/sh覆盖。ENTRYPOINT

我对此的理解是,如果ENTRYPOINT指令存在于我的 Dockerfile 中,那么 Heroku 的容器堆栈将不会执行带有/bin/sh. 但显然我的理解是错误的,因为这似乎仍在发生。

下面是我的 Dockerfile 的示意图:

FROM golang:1.14 as build

# ... builds the binary

FROM scratch

# ... other irrelevant stuff

COPY --from=build /myprogram /myprogram

ENTRYPOINT ["/myprogram"]

最终图像包含基础图像中的二进制/myprogram文件scratch。由于scratch没有/bin/sh,因此有必要覆盖它。根据他们的文档,这是通过ENTRYPOINT.

但是,当我将它部署到 Heroku 时,它似乎仍然使用 shell 执行。为了显示:

% heroku ps -a my-app-name
== web (Free): /bin/sh -c --myflag1 --myflag2 (1)

这意味着它最终正在执行:

/myprogram /bin/sh -c --myflag1 --myflag2

这显然不是我想要的。但是这部分文档(我之前强调过)发生了什么?:

要执行单个二进制文件或使用没有 shell 的图像,请使用ENTRYPOINT

...

heroku.yml 文件如下所示:

---
build:
  docker:
    web: Dockerfile

run:
  web:
    command:
    - --myflag1
    - --myflag2

我仍然对 shell 表单和 exec 表单有同样的问题。意思是,我也尝试使用看起来像这样的 heroku.yml 文件:

---
build:
  docker:
    web: Dockerfile

run:
  web: --myflag1 --myflag2

现在,我知道我可以通过将最终图像基于具有/bin/sh并删除ENTRYPOINT指令的图像来“正常工作”,并使用/myprogram. 我不需要使用从头开始,但我并且应该能够使用scratch,对吧?这是我多年来一直使用的在容器中运行静态链接二进制文件的方法,在其他平台上部署时我从未遇到过这样的问题。

那么我是否误解了他们的文档?我需要做什么才能摆脱这种/bin/sh恶作剧?

4

0 回答 0