Reputation: 139
With a default entrypoint of /bin/sh -c
, I'd expect to see docker run <image ID> echo 'foo'
result in /bin/sh -c echo 'foo'
execute which does not print foo (foo is an arg for sh here, not echo).
However, it seems to run as if its quoted/passed in as a single arg to sh. What is the reason for this?
The only reason I can think of is that docker run command(s) are parsed as a single command and handed to /bin/sh -c
as a single item
Upvotes: 1
Views: 767
Reputation: 158908
The sh -c
option takes a single argument, which is parsed and executed as a shell command. If that command has multiple words, you need to quote it so it gets passed as a single argument.
This isn't Docker-specific and you can see it in a local shell:
$ echo 'foo'
foo
$ /bin/sh -c echo 'foo'
$ /bin/sh -c "echo 'foo'"
foo
If there are additional parameters, the sh -c
command can see them as positional parameters, starting with $0
.
$ sh -c 'echo "$2"' foo bar baz quux
baz
In a more Docker-specific context, you can see the same behavior using this as a docker run
command
$ docker run --rm busybox sh -c 'echo "$2"' foo bar baz
baz
In a Dockerfile, RUN, CMD, and ENTRYPOINT will automatically add the sh -c
wrapper so you don't need to explicitly specify it.
# same:
CMD ls && exec main_program
CMD ["/bin/sh", "-c", "ls && exec main_program"]
# unnecessary extra sh -c:
CMD sh -c 'ls && exec main_program'
CMD ["/bin/sh", "-c", "main_program"] # without redirects, environment variables, ...
You only need the explicit sh -c
if you have a complex command as a docker run
or Compose command:
override command.
Upvotes: 3