Dockerfile CMD for taking bash commands from host - bash

I've created a dockerfile with various compile and build tools. The goal of the dockerimage is to standardize our development tools, and make it easy and consistent for developing.
Everything is installed.
What I am stuck on, is how to make the docker container keep running, and be able to have a bash shell to that container so that I can run, for example, make etc. ?
If I use ENTRYPOINT /bin/bash my container exits immediately. How to keep the container running?

You should use the command at run time. You run your Docker container in interatice mode (-i) and set the command to "/bin/bash":
docker run -it myDockerImage myCommandToExecuteInteractively
For instance:
docker run -it myDocker /bin/bash
Here is a real life example:
a) Pulling the most basic image
docker pull debian:jessie-slim
b) Let's have a bash there:
docker run -it debian:jessie-slim /bin/bash
c) Enjoy:

A docker container will run as long as the CMD/Entrypoint from your Dockerfile takes.
You can run your Docker container in interactive mode using switch i
sudo docker run -it --entrypoint=/bin/bash <imagename>
Example : docker run -it --entrypoint=/bin/bash ubuntu:14.04
This will start an interactive shell in your container. Your container will exit as soon as you exit that shell.

Related

Is there a way to reintroduce yourself to a docker container running bash?

Let's say I have one docker container that when run it finishes with bash. So after docker run I have a bash terminal and I can put commands.
If for some reason I lost contact to this terminal (it can happen) and then in another terminal, I do docker ps, I can see the container running. However I am not "inside" the bash of this docker
Right now what I do is to delete this and then run docker run again but is there a way I can rejoin the terminal of this running container?
You can "detach" from a container without closing the program by Ctrl-P + Ctrl-Q
docker run -it -d --entrypoint sh busybox
docker attach $container_id
/ # #inside container, use Ctrl-p Ctrl-q to detach

How to get an interactive bash shell in a Docker container

I'm trying to connect to a running container or start a new container in interactive mode with the bash shell -- not the sh shell. I want to run:
docker exec -it <container_name> /bin/bash
or
docker run -it <container_name> <image_name>
or
docker run -it <container_name> <image_name> /bin/bash
and get an interactive bash shell.
What I've tried so far:
Per this post I've tried
Adding this to my Dockerfile
SHELL ["/bin/bash", "-c"]
Adding this to my Dockerfile
RUN ["/bin/bash", "-c", "echo I am now using bash!"]
But every time I try to run a container in interactive mode (docker run -it or attach to a running container (docker exec -it), I land in the sh shell.
How can I get an interactive bash shell that is running inside a docker container?
Update: Minimal working Dockerfile
FROM ubuntu
SHELL ["/bin/bash", "-c"]
You are in fact running an interactive bash with commands like:
docker container run -it ubuntu /bin/bash
When you run bash in a docker container, that shell is in a container. So it won't have the command history from outside of the container, that history is maintained on the host filesystem. It also won't have your prompt, the PS1 variable is not automatically exported into the container's environment. And it won't have your .bashrc configuration from your host, since that isn't inside the container. Instead you get a bash shell that is out of the box from a minimal ubuntu host.

How do I Run Docker cmds Exactly Like in a Dockerfile

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?
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
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 by ENTRYPOINT command in Dockerfile. Ie if cmd is my-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

How do you start a Docker-ubuntu container into bash?

The answers from this question do not work.
The docker container always exits before I can attach or won't accept the -t flag. I could list all of the commands I've tried, but it's a combination of start exec attach with various -it flags and /bin/bash.
How do I start an existing container into bash? Why is this so difficult? Is this an "improper" use of Docker?
EDITS:
I created the container with docker run ubuntu. The information about the container: 60b93bda690f ubuntu "/bin/bash" About an hour ago Exited (0) 50 minutes ago ecstatic_euclid
First of all, a container is not a virtual machine. A container is an isolation environment for running a process. The life-cycle of the container is bound to the process running inside it. When the process exits, the container also exits, and the isolation environment is gone. The meaning of "attach to container" or "enter an container" actually means you go inside the isolation environment of the running process, so if your process has been exited, your container has also been exited, thus there's no container for you to attach or enter. So the command of docker attach, docker exec are target at running container.
Which process will be started when you docker run is configured in a Dockerfile and built into a docker image. Take image ubuntu as an example, if you run docker inspect ubuntu, you'll find the following configs in the output:
"Cmd": ["/bin/bash"]
which means the process got started when you run docker run ubuntu is /bin/bash, but you're not in an interactive mode and does not allocate a tty to it, so the process exited immediately and the container exited. That's why you have no way to enter the container again.
To start a container and enter bash, just try:
docker run -it ubuntu
Then you'll be brought into the container shell. If you open another terminal and docker ps, you'll find the container is running and you can docker attach to it or docker exec -it <container_id> bash to enter it again.
You can also refer to this link for more info.
Here is a very simple Dockerfile with instructions as comments ... launch it to spin up a running container you can exec login to
FROM ubuntu:20.04
ENV TERM linux
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update
RUN apt-get install -y
CMD ["/bin/bash"]
# ... save this file as Dockerfile then in same dir issue following
#
# docker build --tag stens_ubuntu . # creates image stens_ubuntu
#
# docker run -d stens_ubuntu sleep infinity # launches container
#
# docker ps # show running containers
#
#
# ... find CONTAINER ID from above and put into something like this
#
# docker exec -ti $( docker ps | grep stens_ubuntu | cut -d' ' -f1 ) bash # login to running container
# docker exec -ti 3cea1993ed28 bash # login to running container using sample containerId
#
A container will exit normally when it has no work to do ... if you give it no work it will exit immediately upon launch for this reason ... typically the last command of your Dockerfile is the execution of some flavor of a server which stays alive due to an internal event loop and in so doing keeps alive its enclosing container ... short of that you can mention a server executable which has been installed into the container as the final parameter of your call to
docker run -d my-image-name my-server-executable

docker run ubuntu on mac and nothing happens

i'm on mac running:
docker is configured to use the default machine with IP 192.168.99.100
For help getting started, check out the docs at https://docs.docker.com
my-mac:mydir$ docker run ubuntu /bin/bash
my-mac:mydir$
am i doing something wrong? shouldn't I get into the ubuntu shell?
By running docker run ubuntu /bin/bash, docker create a randomly-named container from the image ubuntu and runs a bash without stdin, stdout nor stderr then bash exits (right after being started).
Try at least to set a tty and interactive mode (aka foreground mode):
docker ps -a
# if not exited, stop it first
docker stop <container_id>
# remove the container which cannot be used
docker rm <container_id>
# let's try again
docker run -it --rm --name=test ubuntu bash
As commented by physincubus:
'-it' is the bit that makes it interactive,
'--rm' removes the container when you exit (so if you want to be able to exit for detach and reattach later, do not do this), and
'--name' allows you to name the container more explicitly in case you want to run multiple instances of the same container
Run it with following command
docker run -it ubuntu /bin/bash
Then you will get bash prompt of ubuntu container

Resources