What does -it exactly do in docker? [duplicate] - docker

This question already has answers here:
what is docker run -it flag?
(3 answers)
Closed 22 days ago.
When executing this command, I can't just leave out neither i nor t to get the bash to work.
sudo docker exec -it 69e937450dab bash
What does it exactly do? When do I need the command without these parameters?

The flags -i and -t are required to run an interactive shell session in the container:
-i makes the session interactive by keeping STDIN open even if not attached
-t allocates a pseudo-TTY, allowing you to interact with the container using a terminal

I will answer it myself:
Normal execution without any flags:
[ec2-user#ip-172-31-109-14 ~]$ sudo docker exec 69e937450dab ls
bin
boot
dev
docker-entrypoint.d
docker-entrypoint.sh
etc
If your command needs an input like cat, you can try:
[ec2-user#ip-172-31-109-14 ~]$ echo test | sudo docker exec 69e937450dab cat
Nothing will show, because there is no input stream going to the docker container. This can be achieved with the -i flag.
[ec2-user#ip-172-31-109-14 ~]$ echo test | sudo docker exec -i 69e937450dab cat
test
Now, let us suppose, you want the bash to start as process:
sudo docker exec 69e937450dab bash
You will see nothing, because the process started in the container. Adding the flag will do the deal:
[ec2-user#ip-172-31-109-14 ~]$ sudo docker exec -t 69e937450dab bash
root#69e937450dab:/#
But this does not really help, because we need an input stream, which takes our commands and can be received by the bash. Therefore, we need to combine the two:
[ec2-user#ip-172-31-109-14 ~]$ sudo docker exec -i -t 69e937450dab bash
root#69e937450dab:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc hi home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root#69e937450dab:/#
small recap:
-t for attaching the bash process to our terminal
-i for being able to send inputs via STDIN for example with the keyboard to the bash in the container
Without -i can be used for commands, that don't need inputs. Without -t and bash can be used, when you just want to use one command.

Related

Even without docker exec -t, the output is there

I understood docker's -t as a kind of virtual terminal that seems to access the terminal through /dev/pts. So, if I do echo "hello, tty" > /dev/pts/1 , I see that it is output to the connected terminal. Since the -i option is STDIN, the container understands it as an option to receive text as input. So, who does the input go to when only the -i option is applied?
Below is the result of the command given only the -i option.
~ $ docker exec -i mysql-container bash
tty
not a tty
ls
bin
boot
dev
docker-entrypoint-initdb.d
entrypoint.sh
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
I didn't give the -t option, so I was expecting no results back. But it exactly missed my expectations. Why is it running like this?
The difference is subtle, but when you only use -i, you communicate with it using stdin and stdout. But there's no terminal in the container.
When you use -it you attach a terminal and that lets you do 'terminal stuff'. For instance, with -it
you get a prompt
you can send programs to the background with stuff like tail -f /dev/null &
ctrl-c works as expected
etc
The difference is hard to spot, because with -i you usually take stdin from a terminal on the host and send stdout to the a terminal on the host.
Usually, when you want to run commands interactively, you'll use -it. A scenario where you might use only -i is when you pipe the commands into the container. Something like this
echo -e 'tty\nls' | docker exec -i mysql-container bash
which will run the tty and ls commands and give you the output.

How to handle prompt in Docker Exec

I try to execute the following line:
docker exec --user www-data nextcloud_docker php /var/www/html/occ db:convert-filecache-bigint
which returns a prompt:
This can take up to hours, depending on the number of files in your instance!
Continue with the conversion (y/n)? [n]
Unfortunately the docker exec command ends (returns to shell) and I am not able to start the occ command.
How can I solve this?
Thanks.
You can try setting the -i flag on the docker command and piping a 'y' into it, like this
echo y | docker exec -i --user www-data nextcloud_docker php /var/www/html/occ db:convert-filecache-bigint
or you can run the command fully interactively with the -it flags like this
docker exec -it --user www-data nextcloud_docker php /var/www/html/occ db:convert-filecache-bigint
occ has a -n switch.
I run it from cron, including the update. I have these lines in /home/update-nextcloud-inside-container.sh inside my container:
#!/bin/bash
date
sed -i 's~www-data:/var/www:/usr/sbin/nologin~www-data:/var/www:/bin/bash~g' /etc/passwd
su -c "cd /var/www/nextcloud; php /var/www/nextcloud/updater/updater.phar --no-interaction" www-data
su -c "cd /var/www/nextcloud; ./occ db:add-missing-indices -n" www-data
su -c "cd /var/www/nextcloud; ./occ db:convert-filecache-bigint -n" www-data
sed -i s~www-data:/var/www:/bin/bash~www-data:/var/www:/usr/sbin/nologin~g /etc/passwd
and the host cron launches a script with these lines:
ActiveContainer=$(/home/myusername/bin/lsdocker.sh | grep next )
docker exec -i ${ActiveContainer} /home/update-nextcloud-inside-container.sh
I see now I am missing taking the instance off-line for running convert-filecache. I'll have to add that.
Edit: (lsdocker.sh is a script that uses docker ps to list just the active container names)

Listing files from outside docker does not work but from within does

What's wrong with the following statement ?
sudo docker exec myDockerName ls -lt /var/lib/myApp/data/myFolder/debian*.gz
this returns No such file or directory
but running the command being within the docker, returns the desired results
sudo docker exec -it myDockerName bash
ls -lt /var/lib/myApp/data/myFolder/debian*.gz
does docker ls work differently ?
I think that passing your arguments as a string can solve this issue, using the -c flag:
sudo docker exec myDockerName bash -c "ls -lt /var/lib/myApp/data/myFolder/debian*.gz"

what is docker run -it flag?

I was doing some complex stuff with docker, but as turn out I don't know what -it flag means.
Recently I've come across on some example of docker run command which has confused me a little.
docker run -itd ubuntu:xenial /bin/bash
My question is what is sense to write -it flag here, if container during instantiation run bin/bash
In documentation we have an example
docker run --name test -it debian
with explanation
The -it instructs Docker to allocate a pseudo-TTY connected to the
container’s stdin; creating an interactive bash shell in the
container.
and explanation for -t flag from help page
-t, --tty Allocate a pseudo-TTY
if I delete -it flag during
docker run -d ubuntu:xenial /bin/bash
my newly created container doesn't live so much
in docker ps -a
it is designated as exited
Sorry, if my question quite stupid, I can't find explanation on the Internet (I have significant misunderstanding of that point).
-it is short for --interactive + --tty. When you docker run with this command it takes you straight inside the container.
-d is short for --detach, which means you just run the container and then detach from it. Essentially, you run container in the background.
Edit: So if you run the Docker container with -itd, it runs both the -it options and detaches you from the container. As a result, your container will still be running in the background even without any default app to run.
docker run -it ubuntu:xenial /bin/bash starts the container in the interactive mode (hence -it flag) that allows you to interact with /bin/bash of the container. That means now you will have bash session inside the container, so you can ls, mkdir, or do any bash command inside the container.
The key here is the word "interactive". If you omit the flag, the container still executes /bin/bash but exits immediately. With the flag, the container executes /bin/bash then patiently waits for your input.
Normal execution without any flags:
[ec2-user#ip-172-31-109-14 ~]$ sudo docker exec 69e937450dab ls
bin
boot
dev
docker-entrypoint.d
docker-entrypoint.sh
etc
If your command needs an input like cat, you can try:
[ec2-user#ip-172-31-109-14 ~]$ echo test | sudo docker exec 69e937450dab cat
Nothing will show, because there is no input stream going to the docker container. This can be achieved with the -i flag.
[ec2-user#ip-172-31-109-14 ~]$ echo test | sudo docker exec -i 69e937450dab cat
test
Now, let us suppose, you want the bash to start as process:
sudo docker exec 69e937450dab bash
You will see nothing, because the process started in the container. Adding the flag will do the deal:
[ec2-user#ip-172-31-109-14 ~]$ sudo docker exec -t 69e937450dab bash
root#69e937450dab:/#
But this does not really help, because we need an input stream, which takes our commands and can be received by the bash. Therefore, we need to combine the two:
[ec2-user#ip-172-31-109-14 ~]$ sudo docker exec -i -t 69e937450dab bash
root#69e937450dab:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc hi home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root#69e937450dab:/#
small recap:
-t for attaching the bash process to our terminal
-i for being able to send inputs via STDIN for example with the keyboard to the bash in the container
Without -i can be used for commands, that don't need inputs. Without -t and bash can be used, when you dont want to attach the docker containers process to your shell.

docker exec command not executing in sh file

When running below command in command line(terminal) this gets executed fine:
$sudo docker exec -it 5570dc09b58 bash
But same results with :
FATA[0000] cannot enable tty mode on non tty input
Error when running in a shell script file.
Scripts may be forced to run in interactive mode with the -i option or with a #!/bin/bash -i header.
So adding shebang to the script with -i option should work:
#!/bin/bash -i
docker exec -it ed3d9e46b8ee date
Run the script as usual:
chmod +x run.sh
sudo ./run.sh
Output:
Thu Apr 2 14:06:00 UTC 2015
You are not running docker in a terminal, so you should remove -t from -it:
sudo docker exec -i 5570dc09b58 bash
See a more detailed answer here.
There are few images which do not support the interactive shell/bash.
Example - Docker image mockserver/mockserver
Docker Set Up

Resources