问题
There seems to be a difference between how Docker runs commands in a Dockerfile versus running commands manually after starting a container. This seems to be due to the kind of shells you can start, a (I assume) non-interactive shell with a Dockerfile vs an interactive one when running something like docker run -it <some-img-id>
.
How can I debug running commands in a Docker container so that it runs exactly like the commands are run from a Dockerfile? Would just adding /bin/bash --noprofile
to the run
cmd suffice? Or is there anything else different about the environment when started from a Dockerfile?
回答1:
What you are experiencing is the behavior because of the shell. Most of us are used to using the bash shell. So generally we would attempt to run the commands in the below fashion
For new container
docker run -it <imageid> bash
For existing container
docker exec -it <containerid> bash
But when we specify some command using RUN
directive inside a Dockerfile
RUN echo Testing
Then it is equivalent to running /bin/sh -c 'echo Testing'
. So you can expect certain differences as both the shells are different.
In Docker 1.12 or higher you have a Dockerfile directive named SHELL
this allows you to override the default SHELL
SHELL ["/bin/bash", "-c"]
RUN echo Testing
This would make the RUN
command be executed as bash -c 'echo Testing'
. You can learn more about the SHELL
directive here
回答2:
Short answer 1:
If Dockerfile don't use USER
and SHELL
commands, then this:
docker --entrypoint "/bin/sh -c" -u root <image> cmd
Short answer 2:
If you don't squash or compress image after the build, Docker creates images layers for each of the Dockerfile commands. You can see them in the output of docker build
at the end of each step with --->
:
Step 2/8 : WORKDIR /usr/src/app
---> 5a5964bed25d # <== THIS IS IMAGE ID OF STEP 2
Removing intermediate container b2bc9558e499
Step 3/8 : RUN something
---> f6e90f0a06e2 # <== THIS IS IMAGE ID OF STEP 3
Removing intermediate container b2bc9558e499
Look for the image id just before the RUN step you want to debug (for example you want to debug step 3 on above, take the step 2 image id). Then just run the command in that image:
docker run -it 5a5964bed25d cmd
Long answer 1:
When you run docker run [image] cmd
Docker in fact starts the cmd
in this way:
- Executes the default entrypoint of the image with the
cmd
as its argument. Entrypoint is stored in the image on build byENTRYPOINT
command in Dockerfile. Ie ifcmd
ismy-app
and entrypoint is/bin/sh -c
, it executes/bin/sh -c my-app
. - Starts it with default user id of the image, which is defined by the last
USER
command in Dockerfile - Starts it with the environment variables from all
ENV
commands from image's Dockerfile commulative
When docker build
runs the Dockerfile RUN
, it does exatly the same, only with the values present at that time (line) of the Dockerfile.
So to be exact, you have to take the value of ENVs and last USER command before your RUN line, and use those in the docker run
command.
Most common images have /bin/sh -c
or /bin/bash -c
as entrypoint and most likely the build operates with root user. Therefore docker --entrypoint "/bin/bash -c" -u root <image> cmd
should be sufficient
来源:https://stackoverflow.com/questions/45393971/how-do-i-run-docker-cmds-exactly-like-in-a-dockerfile