0

I'm building a docker image based on some other image that is out of my control. The base image sets an ENTRYPOINT I want to use by simply passing arguments via the CMD command. I also need to use runtime variable expansion in the arguments. Here's my Dockerfile

FROM base # I do not control base, but I need to call its ENTRYPOINT.

# The "as default parameters to ENTRYPOINT" form. Does not expand variables.
CMD [ "--port", "$PORT" ]

# The "exec" from. I can't use it, because I do not know path to the executable as the base image is outside my control.
CMD [ "executable", "--port", "$PORT" ]

# The "shell" form. Won't even build because "--port" is interpreted as flag of "CMD".
CMD --port $PORT

As explained in the code, none of the three forms offered by the docs works in my use case.

There are already similar question here on SO, but neither answers this particular use case. This one doesn't comprise variable expansion. And this one doesn't account for the inability to change the ENTRYPOINT.

Jen
  • 1,206
  • 9
  • 30
  • Can you point us at the `base` image? Even though you can't modify it, understanding what the `ENTRYPOINT` looks like might help. Note also that your "exec form" doesn't do what you think...it's identical to the previous example, but simply passes three instead of two parameters to the `ENTRYPOINT`. Also, where are you setting `$PORT`? – larsks Feb 04 '21 at 23:23
  • 2
    Note also that *of course* you can change the `ENTRYPOINT` by simply re-defining it in your `Dockerfile`. – larsks Feb 04 '21 at 23:25
  • @larsks The base image is [this one](https://hub.docker.com/r/maptiler/tileserver-gl). I know, I can override the ENTRYPOINT myself, but then I'll depend on the location of the executable withing the base image. I thought that this location is rather an implementation detail one shouldn't depend on while ENTRYPOINT is the canonical way for the base image to expose this location. – Jen Feb 05 '21 at 00:10

1 Answers1

2

You can't use CMD with variable expansion in this case.

Docker on its own doesn't know how to expand variables in the container command. As you note, there are two syntaxes:

  1. CMD ["cmd", "$option"] literally passes cmd and $option as arguments with no expansion at all
  2. CMD cmd $option just wraps that string in a shell invocation, equivalent to CMD ["sh", "-c", "cmd $option"], and depends on that shell to do the expansion.

In a comment you mention a specific image. If you look at its generated history this uses the "container as command" pattern, where the ENTRYPOINT is a command to launch and the CMD is arguments to that command. Unless the command specifically expects to receive sh and -c as options, this won't work; but the sh -c wrapper is the only way Docker has to cause variable expansion at startup time.


You more specifically are trying to pass a --port option. That affects the port the process inside the container listens on. Since the container runs in an isolated network namespace, there's not usually a reason to need to change this: even if you have a dozen containers all listening on the standard HTTP port 80, they won't conflict.

If you want to connect from outside Docker to the container, you only need to change the docker run -p port mapping. Again, the image documentation suggests launching the image with docker run -p 8080:80 to cause it to be accessible from host port 8080; if you want a different host port, change that number, and leave the second port number the same.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Right. Thanks for assuring I'm not just overlooking something. It seems that the question comes down to: Is it conceptually OK to override an ENTRYPOINT of an image I do not control with an explicit path to the original executable? I thought that would make me depend on an *implementation detail* of the base image. OTOH, If I pin the base image to a specific version there's nothing to fear about. .) ad port: I choose the port as an easy to convey example. In reality I'm using an option that needs to be set on runtime (`--public_url`). At least in our case. – Jen Feb 05 '21 at 00:39