3

I am going to change my permission of files to 600. The following command works perfectly.

RUN /bin/bash -c 'chmod 600 /root/.ssh/config'

But this one failed

CMD /bin/bash -c 'chmod 600 /root/.ssh/config'

In the beginning, I thought the shell environment isn't bash so caused the error. However, adding bin/bash didn't solve the issue.

0
3

Note: Don’t confuse RUN with CMD. RUN actually runs a command and commits the result; CMD does not execute anything at build time, but specifies the intended command for the image.

reference

0
3

TL;DR: RUN performs the step during the image build, CMD is the default command when you start a container. If you define CMD and then start your container with a different command (e.g. docker run $my_image /bin/bash), you'll never see it run since you replaced your chmod command with an empty /bin/bash command.


The detailed explanation:

The RUN command creates a temporary container based off of the previous step of the build, executes your selected command, and when the command returns it captures the filesystem changes as a new layer of your image. Run is the equivalent of doing a docker run + docker commit to generate your image, but with a reproducible process.

The CMD command replaces the current value of the image metadata for the command value that you can see when you inspect the image. You can only have one value for CMD for your image. You can also easily override the value of the image command by passing any string after the image name, e.g. docker run busybox echo hello replaces the default /bin/sh command with an echo hello command for that specific container.

There's also ENTRYPOINT which defines the entrypoint for your image. When you define an entrypoint, any value for CMD gets passed as arguments to the entrypoint when starting your container (a container is only started with a single process as pid 1 and exits when that process exits).


Shell vs Exec syntax: Note that each of these accepts a command to run in two forms, the shell/string form, and the exec/json form. The shell form is anything that isn't a json list, and the result command is run as /bin/sh -c "$your_string_here". A shell is useful for IO redirection, chaining commands, and variable expansion. But a shell will also intercept signals which can cause issues when the container is stopped. The exec form runs your command directly in the OS without a shell, which is better for signals, but lacking all the other shell features. When you chain an entrypoint and cmd together, you almost always want the exec syntax since /bin/sh -c only accepts one argument. It's common to run a shell script but have the last command run be an exec which replaces the shell. E.g. a common entrypoint structure is:

Dockerfile:

ENTRYPOINT ["/entrypoint.sh"]
CMD ["server", "arg1", "arg2"]

entrypoint.sh:

#!/bin/sh
# ... steps to setup the host, make configs, fix permissions, copy files, etc ...
# ...
# now run the value of CMD, replacing this shell as pid 1:
exec "$@"
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.