How do you start a Docker-ubuntu container into bash? - 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

Related

Docker container exits as soon as I start it

When I run or start a Docker container, it will not stay running.
Docker start will just return the name of whatever container I gave it, but wont actually do anything. Docker run (ex $ docker run -p 8080:80 --name hello -d hello-world) will create it but it will exit immediately.
If I run docker ps after one of these, it will show nothing listed as currently running.
If I run docker ps -a, it will show all of my containers and show the one that I just attempted to run having exited a few seconds ago.
Is this common and how do I get my containers to stay running? I am trying to learn how to use Docker and it has been one of the worst experiences. Thank you for any help or suggestions
Docker containers are generally used to run applications/processes in an isolated environment.
When you run the hello-world image, it creates a container which has only purpose of printing out the name using standard output. That is the only process that ran and the container was done with its work. That is why you see nothing when done docker ps.
In order to keep a container running, you need to have a process inside that container that will run (for example: a server, database, application etc.)
Try creating a container form mysql image, and then check the running container.
In your command, you specify the -d flag (aka detach), which means Run container in background and print container ID (from Docker docs). See more discussion about this here: Docker container will automatically stop after "docker run -d"
docker run -p 8080:80 --name hello -d hello-world
If you run it without the -d flag, it should run in the foreground and send output to your terminal
docker run -p 8080:80 --name hello hello-world
You don't see it running in docker ps -a because that container just executes the hello-world script and exits. If the container starts a long running process then you'll be able to find it in docker ps -a. To verify this, you can try running the nginx demo containers (e.g. nginx-hello) which serve up 'hello world'/demo pages.
To know what's wrong with your container use (docker logs (your container name)) command.
then you can sort it out what went wrong with your container
Is this common and how do I get my containers to stay running?
What happen when you start a Docker container ?
By default, it executes the command/the entrypoint specified in the Dockerfile image.
Generally that command or the entrypoint is a script or a program located in the image.
When that script/program exits, the container exits too. That's all.
To keep a container alive, the script/program has to stay running.
You start an hello image container, a "hello" container says "hello" and exits.
That may be a script as simple as :
#!/bin/sh
echo "hello"
So that is expected to finish and exit the container.
Run a database or a web server and you will see a different behavior. The script/program keeps running... while you don't stop that. So the container also stays running while you don't stop that.
To experiment, you can run your hello-world container with an endless command :
docker run -p 8080:80 --name hello -d hello-world --entrypoint tail -f /dev/null
You will see that the container stays running.
A docker container exits when its main process finishes. The hello-world main process just prints some text and exits, so container exits too.
You can run this command straightly to see it's text:
docker run hello-world
If you want a running container, maybe you can try a nginx demo:
docker run --name nginx-demo -p 8080:80 -d nginx
then you can visit http://localhost:8080 using your web browser.

Dockerfile CMD for taking bash commands from host

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.

DockerFile : how to get bash command line after start?

This question is not duplicated, because I want to obtain an interactive shell without running with -it flags.
I'm moving first steps into Docker to create images only for internal use.
I start from this envirornment_full.df:
FROM ubuntu:16.04
ENTRYPOINT ["/bin/bash"]
I then build
docker rmi environment:full
docker build -t environment:full -f environment.df .
Then run
docker run environment:full
Running docker images -am I see my image
REPOSITORY TAG IMAGE ID CREATED SIZE
environment full aa91bbd39167 4 seconds ago 129 MB
So I run it
docker run environment:full
I see nothing happening ....
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5847c0a18f30 environment:full "/bin/bash" 21 seconds ago Exited (0) 20 seconds ago admiring_mirzakhani
Also
$ docker run environment:full -ti
bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell
root#aa768a585f33:/# exit
I'd like to have the ubuntu prompt, like if I was in a SSH connection. And this without user must enter -i or -tty flags.
How can I realize this?
bash won't run at all if stdin is closed. If you don't provide the -i flag, bash will simply exit immediately. So when you...
docker run environment:full
...bash exits immediately, and so your container exits. You would see it if you ran docker ps -a, which shows container that have stopped.
bash won't give you an interactive prompt if it's not attached to a tty. So if you were to run...
coerk run -i environment:full
...you would get a bash shell, but with no prompt, or job control, or other features. You need to provide -t for Docker to allocate a tty device.
You can't get what you want without providing both the -i and -t options on the command line.
An alternative would be to set up an image that runs an ssh daemon, and have people ssh into the container. Instead of behaving "like if I was in a SSH connection", it would actually be an ssh session.
Also, note that this:
docker run environment:full -ti
Is not the same as this:
docker run -it environment:full
The former will run bash -ti inside a container, while the latter passes the -i and -t options to docker run.

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

How can I run a docker container and commit the changes once a script completes?

I want to set up a cron job to run a set of commands inside a docker container and then commit the changes to the docker image. I'm able to run the container as a daemon and get the container ID using this command:
CONTAINER_ID=$(sudo docker run -d my-image /bin/sh -c "sleep 10")
but I'm having trouble with the second part--committing the changes to the image once the sleep 10 command completes. Is there a way for me to tell when the docker container is about to be killed and run another command before it is?
EDIT: As an alternative, is there a way to trigger ctrl-p-q via a shell script in the container to leave the container running but return to the host?
There are following ways to persist container data:
Docker volumes
Docker commit
a) create container from ubuntu image and run a bash terminal.
$ docker run -i -t ubuntu:14.04 /bin/bash
b) Inside the terminal install curl
# apt-get update
# apt-get install curl
c) Exit the container terminal
# exit
d) Take a note of your container id by executing following command :
$ docker ps -a
e) save container as new image
$ docker commit <container_id> new_image_name:tag_name(optional)
f) verify that you can see your new image with curl installed.
$ docker images
$ docker run -it new_image_name:tag_name bash
# which curl
/usr/bin/curl
Run it in the foreground, not as daemon. When it ends the script that launched it takes control and commits/push it
I didn't find any of these answers satisfying, as my goal was to 1) launch a container, 2) run a setup script, and 3) capture/store the state after setup, so I can instantly run various scripts against that state later. And all in a local, automated, continuous integration environment (e.g. scripted and non-interactive).
Here's what I came up with (and I run this in Travis-CI install section) for setting up my test environment:
#!/bin/bash
# Run a docker with the env boot script
docker run ubuntu:14.04 /path/to/env_setup_script.sh
# Get the container ID of the last run docker (above)
export CONTAINER_ID=`docker ps -lq`
# Commit the container state (returns an image_id with sha256: prefix cut off)
# and write the IMAGE_ID to disk at ~/.docker_image_id
(docker commit $CONTAINER_ID | cut -c8-) > ~/.docker_image_id
Note that my base image was ubuntu:14.04 but yours could be any image you want.
With that setup, now I can run any number of scripts (e.g. unit tests) against this snapshot (for Travis, these are in my script section). e.g.:
docker run `cat ~/.docker_image_id` /path/to/unit_test_1.sh
docker run `cat ~/.docker_image_id` /path/to/unit_test_2.sh
Try this if you want an auto commit for all which are running. Put this in a cron or something, if this helps
#!/bin/bash
for i in `docker ps|tail -n +2|awk '{print $1}'`; do docker commit -m "commit new change" $i; done

Resources