Those two CMD
forms are exactly equivalent; Docker turns the first one into the second. See for example the Shell form ENTRYPOINT example in the Dockerfile documentation; the same rules apply to CMD
(and incidentally to RUN
).
Correspondingly, I don't think there's ever a reason to write out CMD ["sh", "-c", "..."]
; use the bare-string form instead.
You may be able to run this using JSON-array form as well
CMD ["node", "-r", "dotenv/config", "www"]
which is very slightly lighter-weight, has a little clearer rules on quoting and escaping, but can't run multiple commands or expand environment variables or redirect to files; or, correspondingly, you can't accidentally have your container do the wrong thing because you forgot to quote an environment variable expansion. You need to make sure you manually break every word in the command into a separate JSON array item. I'd argue this form might be "preferred" if it's an option but it'd be one of the last things I'd look at in a code review.
The exec form may help Ctrl+C actually stop the application, but it's not a guarantee. Also see for example Docker not responding to CTRL+C in terminal.