What is the purpose of the -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 apts
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 thedevpts
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
")
Confused about Docker -t option to Allocate a pseudo-TTY
The -t
option goes to how Unix/Linux handles terminal access. In the past, a terminal was a hardline connection, later a modem based connection. These had physical device drivers (they were real pieces of equipment). Once generalized networks came into use, a pseudo-terminal driver was developed. This is because it creates a separation between understanding what terminal capabilities can be used without the need to write it into your program directly (read man pages on stty
, curses
).
So, with that as background, run a container with no options and by default you have a stdout stream (so docker run | <cmd>
works); run with -i
, and you get stdin stream added (so <cmd> | docker run -i
works); use -t
, usually in the combination -it
and you have a terminal driver added, which if you are interacting with the process is likely what you want. It basically makes the container start look like a terminal connection session.
what does the -i flag do in docker?
Docker's -i
/--interactive
allows you to send commands to the container via standard input ("STDIN"), which means you can "interactively" type commands to the pseudo-tty/terminal created by the -t
switch.
Could you clarify when -it should be used in a docker run command?
Mentioning the docs,
For interactive processes (like a shell), you must use -i -t together in order to allocate a tty for the container process.
Essentially what that does is adding a terminal driver which allows you to interact with your container as a terminal session.
After running your container, you can run docker ps
to get the hash id of your container which you can then access by running:
docker exec -it containeridhash sh
What does it mean to attach a tty/std-in-out to dockers or lxc?
stdin, stdout, and ttys
are related concepts. stdin
and stdout
are the input and output streams of a process. A pseudo terminal (also known as a tty
or a pts
) connects a user's "terminal" with the stdin
and stdout
stream, commonly (but not necessarily) through a shell such as bash
. I use quotes around "terminal" since we really don't use a terminal in the same sense today.
In the case of docker, you'll often use -t
and -i
together when you run processes in interactive mode, such as when starting a bash
shell. In the case of the shell you want to be able to issue commands and read the output.
The code docker uses to attach stdout/stdin
has all the dirty details.
Using '*' in docker exec command
If you want a shell inside the container to expand your glob, you need to... well... actually run a shell inside the container. The one outside the container can't see files inside the container (of course), so it passes ls
the literal pattern, not a list of files in the directory as you intend.
Thus:
docker exec -t t1 sh -c "ls /tmp/sth/*"
...note that I'd usually use single-quotes for the command, but since your host is Windows, using double quotes since they're more likely to work from cmd.exe
.
difference between docker attach and docker exec
2015: There was a commit PR which added to the doc:
Note: This command (
attach
) is not for running a new process in a container.
See:docker exec
.
The answer to "Docker. How to get bash\ssh inside runned container (run -d
)?" illustrates the difference:
(docker >= 1.3) If we use
docker attach
, we can use only one instance of shell.
So if we want to open new terminal with new instance of container's shell, we just need to rundocker exec
if the docker container was started using
/bin/bash
command, you can access it using attach, if not then you need to execute the command to create a bash instance inside the container usingexec
.
As mentioned in this issue:
- Attach isn't for running an extra thing in a container, it's for attaching to the running process.
- "
docker exec
" is specifically for running new things in a already started container, be it a shell or some other process.
The same issue adds:
While
attach
is not well named, particularly because of the LXC commandlxc-attach
(which is more akindocker exec <container> /bin/sh
, but LXC specific), it does have a specific purpose of literally attaching you to the process Docker started.
Depending on what the process is the behavior may be different, for instance attaching to/bin/bash
will give you a shell, but attaching to redis-server will be like you'd just started redis directly without daemonizing.
Update 2022: See more with "Containers 101: attach vs. exec - what's the difference?" (Dec. 2021) from Ivan Velichko:
Extract:
Difference between attach and logs
On the diagram above,
docker attach
streams the container's logs back to the terminal.
However, thedocker logs
command does a similar thing.
So, what's the difference?The logs command provides various options to filter the logs while attach in that regard acts as a simple tail.
But what's even more important is that the stream established by the logs command is always unidirectional and connected to the container's logs, not the container's stdio streams directly.The logs command simply streams the content of the container's logs back to your terminal, and that's it.
So, regardless of how you created your container (interactive or non-interactive, controlled by a pseudo-terminal or not), you cannot accidentally impact the container while using the logs command.However, when attach is used:
- If a container was created in the interactive mode (
-i
), everything you type in the terminal after attach-ing to the container will be sent to its stdin.- You can (intentionally or accidentally) send a signal to the container - for instance, hitting ctrl+c on your end while attached sends
SIGINT
to the container.What does exec command do
The exec command is actually a totally different story.
In the case of attach, we were connecting our terminal to an existing container (read, process).
However, the
exec
commandstarts a totally new container!
In other words,exec
is a form of therun
command (which itself is just a shortcut forcreate
+start
).
Bart reminds us in the comments that docker exec
runs a new command in a running container. Not a "totally new one".
docker run with --interactive and --tty flag
There are two ways in which you can interact with a running container
- attach
- exec
--interactive flag
As you mentioned it already says
Keep STDIN open even if not attached
Which from my understanding means it will read inputs from your terminal/console and reacts or present output to it. If you run docker run --tty alpine /bin/sh
and docker run --tty --interactive alpine /bin/sh
. One with --interactive
will react to it.
attach
Attach to a running process
If the docker container was started using /bin/bash
command, you can access it using attach, if not then you need to execute the command to create a bash instance inside the container using exec
.
More in depth: If docker container is started using /bin/bash
then it becomes containers PID 1 and attach
command will attach you to PID 1.
exec
Creates new process
If you want to create a new process inside container than exec it used like exec
is used to execute apt-get
command inside container without attaching to it or run a node or python script.
Eg: docker exec -it django-prod python migrate
See here -i
is for interactive and -t
is for --tty
that is pseudo-TTY. Interactive so that you can enter if something is prompted by this command.
Related Topics
What Is the Equivalent of Solution Files in Linux C++ Ide
Http Post and Get Using Curl in Linux
Execute Combine Multiple Linux Commands in One Line
How to Detect the Physical Connected State of a Network Cable/Connector
How to Count Number of Files in Each Directory
How to Show a Gui Message Box from a Bash Script in Linux
How to Get 'Find' to Ignore .Svn Directories
Rsync Copy Over Only Certain Types of Files Using Include Option
How to Make Mv Create the Directory to Be Moved to If It Doesn't Exist
How to Check If Smtp Is Working from Commandline (Linux)
Unix: How to Delete Files Listed in a File
Cross-Compile a Rust Application from Linux to Windows
How Do Unix Domain Sockets Differentiate Between Multiple Clients
In Bash, How to Add a String After Each Line in a File
Display Two Files Side by Side
Limitations of Intel Assembly Syntax Compared to At&T
How to Convert \Uxxxx Unicode to Utf-8 Using Console Tools in *Nix