understanding docker run --attach option - linux

I'm a newbie with Docker and I'm pretty stuck at the how the --attach option works with docker run.
I would say that I've somehow understood the following command, as far as I understood with the -it Docker creates a pseudo-tty where the /bin/bash command is executed and the stdin and stdout of my local terminal is linked to the pseudo-tty.
$ docker run --rm -it ubuntu /bin/bash
root#d5e3551114ca:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
What I do not understand is the meaning of the following commands:
In this case I see no output on my local terminal, but in the docker logs I can see that the keystrokes are intercepted and executed
docker run --rm --attach stdin -i ubuntu /bin/bash
Here the container is started and stopped immediatelly
docker run --rm --attach stdin ubuntu /bin/bash
Here the container is started but keystrokes are not intercepted nor the output is shown
docker run --rm --attach stdin -t ubuntu /bin/bash
Here I can see the output but keystrokes are not intercepted
$ docker run --rm --attach stdout -t ubuntu /bin/bash
root#b47a46abdf34:/# ls

Related

How to retain docker alpine container after "exit" is used?

Like for example if I use command docker run -it alpine /bin/sh
it starts a terminal after which I can install packages and all. Now when I use exit command it goes back to the terminal. (main one)
So how can I access the same container again?
When I run that command again, I get a fresh alpine.
Please help
The container lives as long as the specified run command process is still running. When you specify to run /bin/sh, once you exit, the sh process will die and so will you container.
If you want to keep your container running, you have to keep the process inside running. For your case (I am not sure what you want to acheive, I assume you are just testing), the following will keep it running
docker run -d --name alpine alpine tail -f /dev/null
Then you can sh into the container using
docker exec -it alpine sh
Pull an image
docker image pull alpine
See that image is there
docker image ls OR just docker images
see what is inside the alpine
docker run alpine ls -al
Now your question is how to stay with the shell
docker container run -it alpine /bin/sh
You are inside shell script command line. Some distribution may have bash shell.
docker exec -it 5f4 sh
/ # (<-- you can run linux command here!)
At this point, you can use command line of alpine and do
ls -al
type exit to come out-
You can run it in detached mode and it will keep running.
With exec command we can login again
docker container run -it -d alpine /bin/sh
verify that it is UP and copy the FIRST 2 -3 digits of the container ID
docker container ls
login with exec command
docker exec -it <CONTAINER ID or just 2-3 digits> sh
You will need to STOP otherwise it will keep running.
docker stop <CONTAINER ID>
Run Alpine in background
$ docker run --name alpy -dit alpine
$ docker ps
Attach to Alpine
$ docker attach alpy
You should use docker start, which allows you to start a stopped container. If you didn't name your container, you'll need to get it's name/id using docker ps.
For example,
$docker ps
CONTAINER ID IMAGE COMMAND
4c01db0b339c alpine bash
$docker start -i -a 4c01db0b339c
What you should do is below
docker run -d --name myalpine alpine tail -f /dev/null
This would make sure that your container doesn't die. Now whenever you need to install packages inside you just get inside the container using sh
docker exec -it myalpine /bin/sh
If for some reason your container dies, you can still start it again using
docker start myalpine

Docker tool in Jenkins container (with mounted Docker socket) is not finding a Docker daemon to connect to

I just started a Jenkins docker container with a mounted docker socket like the following:
docker run -d \
--publish 8080:8080 \
--publish 50000:50000 \
--volume /my_jenkins_home:/var/jenkins_home \
--volume /var/run/docker.sock:/var/run/docker.sock \
--restart unless-stopped \
--name my_jenkins_container \
company/my_jenkins:latest
Then I bash into the container like this:
docker exec -it my_jenkins_container bash
A tool 'docker' command in a Jenkins pipeline script has automatically installed a Docker binary at the following path: /var/jenkins_home/tools/org.jenkinsci.plugins.docker.commons.tools.DockerTool/docker/bin/docker
However, when I try to run Docker commands from that Docker binary (assuming that it will connect with the Docker socket that has been mounted at /var/run/docker.sock) it returns the following error:
$ /var/jenkins_home/tools/org.jenkinsci.plugins.docker.commons.tools.DockerTool/docker/bin/docker images
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
How can I ensure that this Docker binary (the binary that has been automatically installed via the Jenkins' tool 'docker' command) runs its Docker commands by connecting to the mounted Docker socket at /var/run/docker.sock?
Short Answer:
The file permissions of the mounted Docker socket file had to be revised.
Long Answer:
When I simply tried to execute /path/to/dockerTool/bin/docker ps -a on the Docker container, it was producing an error.
$ docker exec -it my_jenkins_container bash -c "/var/jenkins_home/tools/org.jenkinsci.plugins.docker.commons.tools.DockerTool/docker/bin/docker ps -a"
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
Then, when I tried to execute /path/to/dockerTool/bin/docker ps -a with user=root, it worked fine.
$ docker exec -it --user=root my_jenkins_container bash -c "/var/jenkins_home/tools/org.jenkinsci.plugins.docker.commons.tools.DockerTool/docker/bin/docker ps -a"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9dd56411efe company/my_jenkins:latest "/bin/tini -- /usr/lo" 49 seconds ago Up 49 seconds 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp my_jenkins_container
So it means I just needed to set the right permissions to the Docker socket. All I had to do was chgrp the socket file to the jenkins group so that the jenkins group/users can read/write to that socket file (the before & after of the chgrp command is included here):
$ docker exec -it my_jenkins_container bash -c "ls -l /var/run/docker.sock"
srw-rw---- 1 root 999 0 Jan 15 08:29 /var/run/docker.sock
$ docker exec -it --user=root my_jenkins_container bash -c "chgrp jenkins /var/run/docker.sock"
$ docker exec -it my_jenkins_container bash -c "ls -l /var/run/docker.sock"
srw-rw---- 1 root jenkins 0 Jan 15 08:29 /var/run/docker.sock
After that, executing /path/to/dockerTool/bin/docker ps -a as a non-root user worked fine
$ docker exec -it my_jenkins_container bash -c "/var/jenkins_home/tools/org.jenkinsci.plugins.docker.commons.tools.DockerTool/docker/bin/docker ps -a"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c9dd56411efe company/my_jenkins:latest "/bin/tini -- /usr/lo" 3 minutes ago Up 3 minutes 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp my_jenkins_container

Docker container does not give me a shell

I am trying to get a shell inside the Docker container moul/phoronix-test-suite on Docker Hub using this command
docker run -t -i moul/phoronix-test-suite /bin/bash
but just after executing the command (binary file), the container stops and I get no shell into it.
[slazer#localhost ~]$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0993189463e6 moul/phoronix-test-suite "phoronix-test-suite " 7 seconds ago Exited (0) 3 seconds ago kickass_shockley
It is a ubuntu:trusty container. How can I get a shell into it, so that I can send arguments to the command phoronix-test-suite?
docker run -t -i moul/phoronix-test-suite /bin/bash will not give you a bash (contrary to docker run -it fedora bash)
According to its Dockerfile, what it will do is execute
phoronix-test-suite /bin/bash
Meaning, it will pass /bin/bash as parameter to phoronix-test-suite, which will exit immediately. That leaves you no time to execute a docker exec -it <container> bash in order to open a bash in an active container session.
Have you tried restarting your docker? It might need to restart or even reboot the host.

Docker: Unable to run shell script stored in a mounted volume

I am running Docker (1.10.2) on Windows. I created a script to echo 'Hello World' on my machine and stored it in C:/Users/username/MountTest. I created a new container and mounted this directory (MountTest) as a data volume. The command I ran to do so is shown below:
docker run -t -i --name mounttest -v /c/Users/sarin/MountTest:/home ubuntu /bin/bash
Next, I run the command to execute the script within the container mounttest.
docker exec -it mounttest sh /home/helloworld.sh
The result is as follows:
: not foundworld.sh: 2: /home/helloworld.sh:
Hello World
I get the desired output (echo Hello World) but I want to understand the reason behind the not found errors.
Note: This question might look similar to Run shell script on docker from shared volume, but it addresses permission related issues.
References:
The helloworld.sh file:
#!/bin/sh
echo 'Hello World'
The mounted volumes information is captured below.
Considering the default ENTRYPOINT for the 'ubuntu' image is sh -c, the final command executed on docker exec is:
sh -c 'sh /home/helloworld.sh'
It looks a bit strange and might be the cause of the error message.
Try simply:
docker exec -it mounttest /home/helloworld.sh
# or
docker exec -it mounttest sh -c '/home/helloworld.sh'
Of course, the docker exec should be done in a boot2docker ssh session, simalar to the shell session in which you did a docker run.
Since the docker run opens a bash, you should make a new boot2docker session (docker-machine ssh), and in that new boot2docker shell session, try the docker exec.
Trying docker exec from within the bash made by docker run means trying to do DiD (Docker in Docker). It is not relevant for your test.

What is the purpose of the "-i" and "-t" options for the "docker exec" command?

To be honest, I have always been confused about docker exec -it …, docker exec -i … and docker exec -t …, so I decide to do a test:
docker exec -it …:
# docker exec -it 115c89122e72 bash
root#115c89122e72:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
It works normally.
docker exec -i …:
# docker exec -i 115c89122e72 bash
^C
The command hangs and I have to use Ctl + c to interrupt it.
docker exec -t …:
# docker exec -t 115c89122e72 bash
root#115c89122e72:/# ls
^C
It enters the container successfully but hangs on executing the first command.
So it seems there is no point in having the docker exec -i … and docker exec -t … commands. Could anyone elaborate on why there exist -i and -t options for the docker exec command?
-i, --interactive keeps STDIN open even if not attached, which you need if you want to type any command at all.
-t, --tty Allocates a pseudo-TTY, a pseudo terminal which connects a user's "terminal" with stdin and stdout. (See container/container.go)
If you do an echo, only -t is needed.
But for an interactive session where you enter inputs, you need -i.
Since -i keeps stdin open, it is also used in order to pipe input to a detached docker container. That would work even with -d (detach).
See "When would I use --interactive without --tty in a Docker container?":
$ echo hello | docker run -i busybox cat
hello
-i keeps STDIN open even if not attached, what is the status of STDOUT in this case?
It is, for docker exec, the one set by docker run.
But, regarding docker exec, there is a current issue (issue 8755: Docker tty is not a tty with docker exec
unfortunately your discovery only amounts to a difference between the behaviour of tty in centos6 vs ubuntu:14.04. There is still not a functional tty inside the exec - just do ls -la /proc/self/fd/0 and see that it's a broken link pointing to a pts which doesn't exist.
the actual bug we're dealing with is that certain standard libraries assume that the symlinks in /proc/self/fds/ must be valid symlinks
The problem is that the tty is created outside on the host and there is no reference to it in the container like how /dev/console is setup in the primary container.
One options to fix this would be allocate and bind mount the devpts from the host in to the containers.
Note (Q4 2017): this should been fixed by now (docker 17.06-ce).
See PR 33007.
That PR now allows (since 17.06):
zacharys-pro:dev razic$ docker run --rm -t -d ubuntu bash
83c292c8e2d13d1b1a8b34680f3fb95c2b2b3fef71d4ce2b6e12c954ae50965a
zacharys-pro:dev razic$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
83c292c8e2d1 ubuntu "bash" 2 seconds ago Up 1 second xenodochial_bardeen
zacharys-pro:dev razic$ docker exec -ti xenodochial_bardeen tty
/dev/pts/1
(before 17.06, tty was returning "not a tty")

Resources