Some Dockerfiles have
RUN bash -c "apt-get update -qq && ... \"
while others write without quotes like
RUN apt-get update -qq && ... \
What is the difference between these variants? Is one of them more preferable over another one?
CodePudding user response:
You should just write RUN apt-get update ...
without manually inserting a sh -c
wrapper.
The RUN
, CMD
, and ENTRYPOINT
directives all share the same syntax. It's best documented for ENTRYPOINT
but all three commands work the same way. There are two ways to write commands for them: you can either provide a specific set of command words as a JSON array (exec form), or you can write a string and Docker will automatically wrap it sh -c
(shell form). For example:
# Create a directory with a space in its name
RUN mkdir "a directory"
# JSON-array form: each array element is a shell word
RUN ["ls", "-ld", "a directory"]
# String form: Docker provides a shell, so these two are equivalent
RUN ls -ld 'a directory'
RUN ["/bin/sh", "-c", "ls -ld 'a directory'"]
This makes your first form redundant: if you RUN bash -c '...'
, it's a string, and Docker automatically wraps it in sh -c
. So you get in effect
# RUN bash -c '...'
RUN ["/bin/sh", "-c", "bash -c '...'"]
GNU bash has a number of extensions that are not POSIX-standard syntax and it's possible to run into trouble with these, particularly on an Alpine-based image where /bin/sh
is a minimal shell from the BusyBox toolset. I could see this as an attempt to force a shell command to run using bash rather than the default shell. For most things that appear in Dockerfiles, they won't usually be so complex that they can't be easily rewritten in standard syntax.
# Needs bash for the non-standard `source` syntax
RUN bash -c 'source ./venv/bin/activate && pip list'
# But you can use the standard `.` instead
RUN . ./venv/bin/activate && pip list
If you must have bash interpreting RUN
lines then I'd suggest using the SHELL
directive to change the command that's used to interpret bare strings.
Style-wise, I also occasionally see JSON-array syntax that begins with an explicit CMD ["/bin/sh", "-c", "..."]
. There's no reason to write this out; it's shorter and no less clear to use the string form.