Can't attach to bash running the Docker container - linux

Having troubles with attaching to the bash instance keeping the container running.
To be more detailed. I am running container as here:
$ docker run -dt --name test ubuntu bash
Now it should be actually running, not finished.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
f3596c613cfe ubuntu "bash" 4 seconds ago Up 2 seconds test
After this, I am trying to attach to that instance of bash that keeps the container running. Like this:
$ docker attach test
Running this command I am able to write something to stdin, but no result following. I am not sure if bash is getting lines I typed.
Is there some other way to bash that keeps the container running?
I know, that I can run a different instance of bash and use it docker exec -it test bash. But being more general, is there a way to connect to process that's running in Docker container?
Sometimes it can be useful to save the session of a process running inside the container.
SOLUTION
Thanks to user2915097 for pointing out the missing -i flag.
So now we can have persistent bash session. For example, let's set some alias and reuse after stopping and restarting the container.
$ docker run -itd --name test ubuntu bash
To attach to bash instance just run
$ docker attach test
root#3534cbe1e994:/# alias test="Hello, world!"
To detach from container and not to stop the container press Ctrl+p, Ctrl+q
Then we can stop and restart the container
$ docker stop test
$ docker start test
Now we can attach to the same bash instance and check our alias
$ docker attach test
root#3534cbe1e994:/# test
Hello, world!
Everything is working perfectly!
As I have pointed out in my comment use-case for this can be running some interactive shells as bash, octave, ipython in Docker container persisting all the history, imports, variables and temporary settings just
by reattaching to the same instance.

Your container is running, it is not finished, as you can see
it appears in docker ps, so it is a running container
it show up n seconds
you launch it with -dt so you want it
detached (for d)
allocate a tty (for t)
but not interactive, as you do not add -i
Usually, you nearly always provide -it together, it may be -idt
See this thread
When would I use `--interactive` without `--tty` in a Docker container?
as you want bash, I think you should add -i
I am not sure why you use -d
Usually it is
docker run -it --rm --name=mytest ubuntu bash
and you can test

A container's running lifecycle is determined by its root process, which is bash in your example. When your start your ubuntu container with bash as the process, bash is immediately exiting because it has nothing to keep it running. That's why the container immediately exits and there's nothing to attach to.

Related

Docker keeping CMD alive to exec for inspect. sleep not suitable, ping not avail by default

CMD ['sleep', 100000]
gets stuck and becomes unresponsive for ctrl + c.
Any suggestions?
The issue is when the CMD is not running properly, it is usually easier to exec --it into the server and do those things manually to get them up and running properly.
Without a CMD, run will exit, and therefore exec won't be possible.
I've used sleep for this, but i saw a ping, but ping is not default in ubuntu 18, and perhaps there are better ways than installing it for this simple purpose.
You can provide an alternate command when you run the image. That can be anything you want -- a debugging command, an interactive shell, an alternate process.
docker run --rm myimage ls -l /app
docker run --rm -it myimage bash
# If you're using Compose
docker-compose run myservice bash
This generally gets around the need to "keep the container alive" so that you can docker exec into it. Say you have a container command that doesn't work right:
CMD ["my_command", "--crash"]
Without modifying the Dockerfile, you can run an interactive shell as above. When you get a shell prompt, you can run my_command --crash, and when it crashes, you can look around at what got left behind in the filesystem.
It's important that CMD be a complete command for this to work. If you have an ENTRYPOINT, it needs to use the JSON-array syntax and it needs to run the command that gets passed to it as command line parameters (often, it's a shell script that ends in exec "$#").

Connecting to a specific shell instance in a docker container?

Let's say I have a running docker container my_container. I start a new shell session with:
docker exec -it my_container bash
And then I start a process (a Python script for example), and exit the container with cntrl-p then cntrl-q to keep the script running in the background. If I do this a few different times with a few different scripts, how do I reconnect to a specific shell instance so I can see the std out of my scripts? If I use docker attach my_container, I'm always placed into the first shell instance I initiated when I did my docker run command.
What I usually do is to start tmux inside the first shell. And then start any other processes inside a new window.
Although it is theoretically possible to do so, docker exec still has many issues and it is always better to avoid it for now.
This is a trivial mode, but may be it helps. Instead of "echo "..." substitude with your script names.
Run the container, then run your scripts directly with docker exec and redirect their output to different files.
docker exec -ti containerId /bin/bash -c 'echo "Hello script1" > /var/log/1.log'
docker exec -ti containerId /bin/bash -c 'echo "Hello script2" > /var/log/2.log'
Then you can look at the files by docker exec(uting) some other commands like cat, grep, tail or whatever you want:
docker exec -ti containerId /bin/tail -f /var/log/1.log
docker exec -ti containerId /bin/tail -f /var/log/2.log
Remind you could also use
docker logs containerId
to see the output redirect to /dev/stdout from commands running in the container, but, if I understood your need, in this case you would get the output from many scritps mixed in stdout.

What's the reason Docker Ubuntu official image would exit immediately when you run/start it?

I understand that a container will exit when the main process exit. My question is about the reason behind it, not how to get it to work. I of course know that I could pass the parameter -it to start with interactive mode.
The Ubuntu image will run /bin/bash when it starts according to the image Dockerfile. Shouldn't bash process wait for user input commands and not exit? (just like when you run /bin/bash in the host machine, it would start an interactive shell and wait for user inputs and not exit) Why would the Docker Ubuntu's bash exit right away?
Without -it the container has no TTY, and no stdin attached, so bash starts and completes directly after.
You can keep the container running by adding the -d option (so docker run -dit ubuntu) to start it in detached mode

Why does "docker attach" hang?

I can run an ubuntu container successfully:
# docker run -it -d ubuntu
3aef6e642327ce7d19c7381eb145f3ad10291f1f2393af16a6327ee78d7c60bb
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3aef6e642327 ubuntu "/bin/bash" 3 seconds ago Up 2 seconds condescending_sammet
But executing docker attach hangs:
# docker attach 3aef6e642327
Until I press any key, such as Enter:
# docker attach 3aef6e642327
root#3aef6e642327:/#
root#3aef6e642327:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Why does docker attach hang?
Update:
After reading the comments, I think I get the answers:
prerequisite:
"docker attach" reuse the same tty, not open new tty.
(1) Executing the docker run without daemon mode:
# docker run -it ubuntu
root#eb3c9d86d7a2:/#
Everything is OK, then run ls command:
root#eb3c9d86d7a2:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root#eb3c9d86d7a2:/#
(2) Run docker run in daemon mode:
# docker run -it -d ubuntu
91262536f7c9a3060641448120bda7af5ca812b0beb8f3c9fe72811a61db07fc
Actually, the following should have been outputted to stdout from the running container:
root#91262536f7c9:/#
So executing docker attach seems to hang, but actually it is waiting for your input:
# docker attach 91262536f7c9
ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root#91262536f7c9:/#
It does not really hang. As you can see in the comment below (You are running "/bin/bash" as command) it seems to be expected behaviour when attaching.
As far as I understand you attach to the running shell and just the stdin/stdout/stderr - depending on the options you pass along with the run command - will just show you whatever goes in/out from that moment. (Someone with a bit more in-depth knowledge hopefuly can explain this on a higher level).
As I wrote in my comment on your question, there are several people who have opened an issue on the docker github repo describing similar behaviour:
docker attach [container] hangs, requires input #8521
docker attach hangs setting terminal state when attaching to container
Since you mention shell, I assume you have a shell already running. attach doesn't start a new process, so what is the expected behavior of connecting to the in/out/err streams of a running process?
I didn't think about this. Of course this is the expected behavior of attaching to a running shell, but is it desirable?
Would it be at all possible to flush stdout/stderr on docker attach thereby forcing the shell prompt to be printed or is it a bit more complex than that? That's what I personally would "expect" when attaching to an already running shell.
Feel free to close this issue if necessary, I just felt the need to document this and get some feedback.
Taken from a comment on this github issue. You can find more insight in the comments of this issue.
If instead of enter you would start typing a command, you would not see the extra empty prompt line. If you were to run
$ docker exec -it ubuntu <container-ID-or-name> bash
where <container-ID-or-name> is the ID or name of the container after you run docker run -it -d ubuntu (so 3aef6e642327 or condescending_sammet in your question) it would run a new command, thus not having this "stdout problem" of attaching to an existing one.
Example
If you would have a Dockerfile in a directory containing:
FROM ubuntu:latest
ADD ./script.sh /timescript.sh
RUN chmod +x /timescript.sh
CMD ["/timescript.sh"]
And have a simple bash script script.sh in the same directory containing:
#!/bin/bash
#trap ctrl-c and exit, couldn't get out
#of the docker container once attached
trap ctrl_c INT
function ctrl_c() {
exit
}
while true; do
time=$(date +%N)
echo $time;
sleep 1;
done
Then build (in this example in the same directory as the Dockerfile and script.sh) and run it with
$ docker build -t nan-xiao/time-test .
..stuff happening...
$ docker run -itd --name time-test nan-xiao/time-test
Finally attach
$ docker attach time-test
You will end up attached to a container printing out the time every second. (CTRL-C to get out)
Example 2
Or if you would have a Dockerfile containing for example the following:
FROM ubuntu:latest
RUN apt-get -y install irssi
ENTRYPOINT ["irssi"]
Then run in the same directory:
$ docker build -t nan-xiao/irssi-test .
Then run it:
$ docker run -itd --name irssi-test nan-xiao/irssi-test
And finally
$ docker attach irssi-test
You would end up in a running irssi window without this particular behaviour. Of course you can substitute irrsi for another program.
I ran into this issue as well when attempting to attach to a container that was developed by someone else and already running a daemon. (In this case, it was LinuxServer's transmission docker image).
Problem:
What happened was the terminal appeared to 'hang', where typing anything didn't help and wouldn't show up. Only Ctrl-C would kick me back out.
docker run, docker start, docker attach all was not successful, turns out the command I needed (after the container has been started with run or start) was to execute bash, as chances are the container you pulled from doesn't have bash already running.
Solution:
docker exec -it <container-id> bash
(you can find the container-id from running docker ps -a).
This will pull you into the instance with a functional bash as root (assuming there was no other explicit set up done by the image you pulled).
I know the accepted answer has captured this as well, but decided to post another one that is a little more terse and obvious, as the solution didn't pop out for me when I was reading it.
When I run docker attach container-name, then nothing output, even Ctrl-c is invalid. So, first try
docker attach container-name --sig-proxy=false
and then ctrl-c can stop it. Why it didn't output anything?
just because the container doesn't output. Actually I need to enter my container and run some shell command. So the correct command is
docker exec -ti container-name bash
This happened to me once for the following reason:
It could be that the bash command inside the container is executing a "cat" command.
So when you attach to the container (the bash command) you are actualy inside the cat command which is expecting input. (text and/or ctrl-d to write the file)
If you cannot access command line, just make sure you run your container with -i flag at start.
I just had a similar problem today and was able to fix it:
Here is what was happening for me:
docker-compose logs -f nginx
Attaching to laradock_nginx_1
Then it would hang there until I quit via CTRL-C: ^CERROR: Aborting.
docker ps -a showed that what SHOULD have been called laradock_nginx did not exist with that Image Name, so I figured I'd just remove and re "up" that container:
docker stop cce0c32f7556
docker rm cce0c32f7556
docker-compose up -d laradock_nginx
Unfortunately: ERROR: No such service: laradock_nginx
So I did a sudo reboot and then docker ps -a, but laradock_nginx still wasn't there.
Luckily, docker-compose up -d nginx then worked and docker-compose logs -f nginx now works.
Using: docker exec -it CONTAINER_ID/NAME bash
Instead: docker attach...

docker container started in Detached mode stopped after process execution

I create my docker container in detached mode with the following command:
docker run [OPTIONS] --name="my_image" -d container_name /bin/bash -c "/opt/init.sh"
so I need that "/opt/init.sh" executed at container created. What I saw that the container is stopped after scripts finish executed.
How to keep container started in detached with script/services execution at container creation ?
There are 2 modes of running docker container
Detached mode - This mode you execute a command and will terminate container after the command is done
Foreground mode - This mode you run a bash shell, but will also terminate container after you exit the shell
What you need is Background mode. This is not given in parameters but there are many ways to do this.
Run an infinite command in detached mode so the command never ends and the container never stops. I usually use "tail -f /dev/null" simply because it is quite light weight and /dev/null is present in most linux images
docker run -d --name=name container tail -f /dev/null
Then you can bash in to running container like this:
docker exec -it name /bin/bash -l
If you use -l parameter, it will login as login mode which will execute .bashrc like normal bash login. Otherwise, you need to bash again inside manually
Entrypoint - You can create any sh script such as /entrypoint.sh. in entrypoint.sh you can run any never ending script as well
#!/bin/sh
#/entrypoint.sh
service mysql restart
...
tail -f /dev/null <- this is never ending
After you save this entrypoint.sh, chmod a+x on it, exit docker bash, then start it like this:
docker run --name=name container --entrypoint /entrypoint.sh
This allows each container to have their own start script and you can run them without worrying about attaching the start script each time
A Docker container will exit when its main process ends. In this case, that means when init.sh ends. If you are only trying to start a single application, you can just use exec to launch it at the end, making sure to run it in the foreground. Using exec will effectively turn the called service/application into the main process.
If you have more than one service to start, you are best off using a process manager such as supervisord or runit. You will need to start the process manager daemon in the foreground. The Docker documentation includes an example of using supervisord.

Resources