I can’t say that I know everythng about these parameters, but extending @meyay’s answer here is what I think can help you to understand a little bit better what these parameters are for.
Docker has a client-server architecture. The Docker client is just communicating with the server and tells the server to run a container. The standard input, standard error and standard output streams are still on the server. Normally you wouldn’t see the output or error messages and you wouldn’t be able to run a command on the server that waits for an input since the container is not a child process of the client even if both are on the same machine. This is why Docker Desktop can work because the client can communicate with the server inside the virtual machine.
--attach
can be used to attach to these three streams so the standard input of your client could be forwarded to the standard input of the docker container on the (optionally) remote server, stdout an stderr of the server could be forwarded to your client’s stdout and stderr so you can see the output of the process you run in the container.
--attach
is not compatible with --detach
or -d
which instructs the docker client not to attach to any streams., so the container can “run in the backround”. Well, it always runs in the background. The question is whether the client attaches to the standard streams through the Docker socket or not. For example you can attach to the standard streams, see the output and kill the client process from an other terminal. It will not kill the container.
By default, docker run
will attach to stdout and stderr but not stdin.
docker run --name notstdin bash
ubuntu@docker2:~$ docker container inspect notstdin | grep -i std
"Name": "/notstdin",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"OpenStdin": false,
"StdinOnce": false,
If you use --attach stdin
it will only attach to stdinand nothing else`
docker run --name onlystdin --attach stdin bash
ubuntu@docker2:~$ docker container inspect onlystdin | grep -i std
"Name": "/onlystdin",
"AttachStdin": true,
"AttachStdout": false,
"AttachStderr": false,
"OpenStdin": false,
"StdinOnce": false,
This is what I don’t know what it is for, because it is not enough for the container to be able to read the standard input of the Docker client and you can’t even press CTRL+C to stop the client process.
Let’s say you want to run a container and want to be notified only about errors in the terminal. You can attach the standard error stream without the others.
docker run \
--name onlystderr \
--attach stderr \
bash \
-c 'echo "OUTPUT" > /dev/stdout; echo "ERROR" > /dev/stderr'
# result:
# ERROR
Let’s run: docker logs onlystderr
ERROR
OUTPUT
So the output is written to the logs, you just didn’t see it in real time.
If you inspect the container you will see that only stderr is true:
ubuntu@docker2:~$ docker container inspect onlystderr | grep -i std
"echo \"OUTPUT\" > /dev/stdout; echo \"ERROR\" > /dev/stderr"
"Name": "/onlystderr",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": true,
"OpenStdin": false,
"StdinOnce": false,
"echo \"OUTPUT\" > /dev/stdout; echo \"ERROR\" > /dev/stderr"
You also used -i
(--interactive
) and -t
(--tty
). The interactive flag will make the client attach to all of the streams and you also set OpenStdin
and StdinOnce
to true. Now you run bash without any other foreground process to keep the container alive, but you will not be able to stop the container by pressing CTRL+C.
docker run --name interactive -i bash
The good news is you can actually use bash and see the output in the logs. You can also type “exit” and press ENTER to exit from the shell.
Let’s see the output of the inspect. Everything is enabled except tty:
ubuntu@docker2:~$ docker container inspect interactive | grep -i 'std\|tty'
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": false,
"OpenStdin": true,
"StdinOnce": true,
Using -t
will get you a tty and you can see the bash prompt.
docker run --name interactivetty -it bash
Now Tty is enabled
ubuntu@docker2:~$ docker container inspect interactivetty | grep -i 'std\|tty'
"Name": "/interactivetty",
"AttachStdin": true,
"AttachStdout": true,
"AttachStderr": true,
"Tty": true,
"OpenStdin": true,
"StdinOnce": true,
If you run the container in detached mode using -d
you will have OpenStdin enabled but nothing else, so you are not attached to the standard streams but it is open on the server keeping the bash process alive.
docker run --name interactivedetach --detach -i bash
ubuntu@docker2:~$ docker container inspect interactivedetach | grep -i 'std'
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"OpenStdin": true,
"StdinOnce": false,
What happens when you have an interactive terminal and also attach to standard error but nothing else?
docker run \
--name interactivestderr \
--attach stderr \
-i \
bash \
-c 'echo "OUTPUT" > /dev/stdout; echo "ERROR" > /dev/stderr'
# result:
# ERROR
inspect
ubuntu@docker2:~$ docker container inspect interactivestderr | grep -i 'std'
"echo \"OUTPUT\" > /dev/stdout; echo \"ERROR\" > /dev/stderr"
"Name": "/interactivestderr",
"AttachStdin": true,
"AttachStdout": false,
"AttachStderr": true,
"OpenStdin": true,
"StdinOnce": true,
"echo \"OUTPUT\" > /dev/stdout; echo \"ERROR\" > /dev/stderr"
Here you can see that even if you don’t use --attach stdin
but use -i
, “AttachStdin” will be true, so the standard input will be kept open and you also attach to the standard input from client side.
updated with one more fact
One more important fact is that if you use -t
to get a tty standard output and standard error streams will not be separated so even if you attach to stderr you will not see any output only if you attach to stdout.
ubuntu@docker2:~$ docker run --name ttystderrout -t --attach stderr bash -c 'echo "OUTPUT" > /dev/stdout; echo "ERROR" > /dev/stderr'
ubuntu@docker2:~$ docker run --name ttystderrout2 -t --attach stdout bash -c 'echo "OUTPUT" > /dev/stdout; echo "ERROR" > /dev/stderr'
OUTPUT
ERROR