Heroku with container stack and ENTRYPOINT instruction continues to run with "/bin/sh -c"

Viewed 719

I'll first preface with relevant sections in Heroku's documentation on their container registry and runtime for Docker deploys.

The Docker commands and runtime section states:

  • ENTRYPOINT is optional. If not set, /bin/sh -c will be used
    • CMD will always be executed by a shell so that config vars are made available to your process; to execute single binaries or use images without a shell please use ENTRYPOINT

I want to highlight that last sentence (emphasis added):

to execute single binaries or use images without a shell please use ENTRYPOINT

Furthermore, in the Unsupported Dockerfile commands section.

  • SHELL - The default shell for Docker images is /bin/sh, you can override with ENTRYPOINT if necessary.

My understanding from this is that if the ENTRYPOINT instruction exists in my Dockerfile, then Heroku's container stack will not execute the command with /bin/sh. But apparently my understanding is wrong, because that seems to be still happening.

Here is an illustration of what my Dockerfile looks like:

FROM golang:1.14 as build

# ... builds the binary

FROM scratch

# ... other irrelevant stuff

COPY --from=build /myprogram /myprogram

ENTRYPOINT ["/myprogram"]

The final image contains the binary at /myprogram in a scratch base image. Since scratch doesn't have /bin/sh, it is necessary to override this. According to their documentation, this is done with ENTRYPOINT.

However, when I deploy it to Heroku, it appears to still execute with a shell. To illustrate:

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

Which means it's ultimately executing:

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

Which is obviously not what I want. But what happened to this part of the documentation (which I highlighted earlier)?:

to execute single binaries or use images without a shell please use ENTRYPOINT

...

The heroku.yml file looks like the following:

---
build:
  docker:
    web: Dockerfile

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

I still have the same problem with the shell form and the exec form. Meaning, I also tried with the heroku.yml file looking like this:

---
build:
  docker:
    web: Dockerfile

run:
  web: --myflag1 --myflag2

Now, I know that I can get everything to "just work" by basing the final image on an image that has /bin/sh and remove the ENTRYPOINT instruction, specifying the command with /myprogram. I don't need to use scratch, but I want to, and should be able to use scratch, right? It's what I've been using for many years to run my statically linked binaries in containers and I have never come across problems like this when deploying on other platforms.

So am I misunderstanding their documentation? What do I need to do to get rid of this /bin/sh shenanigan?

0 Answers
Related