recently I learned something about using tty in docker.
I run a shell script in a docker container and want to read from stdin to provide something interactively when attached to the container.
If you just use the command read -p "> " -r line you will get 100% cpu load, if there is no tty connected to the docker container.
To understand what's going on, let's have a look at the following. Run a bash script in a docker container as main process, which executes the command:
lsof -c bash
Depending on how you run the container you get following output:
docker run mycontainer
bash 7 root 0u CHR 1,3 0t0 6 /dev/null
bash 7 root 1w FIFO 0,13 0t0 392981 pipe
bash 7 root 2w FIFO 0,13 0t0 392982 pipe
stdin is connected to /dev/null, which cause 100% cpu load on the read command.
docker run -i mycontainer
bash 7 root 0r FIFO 0,13 0t0 398965 pipe
bash 7 root 1w FIFO 0,13 0t0 398966 pipe
bash 7 root 2w FIFO 0,13 0t0 398967 pipe
the host stdin is connected to the container stdin, but there is no tty.
docker run -t mycontainer
bash 8 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 8 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 8 root 2u CHR 136,0 0t0 3 /dev/pts/0
stdin, stdout, stderr are connected to a tty, but the host stdin is not connected, typing commands is not possible.
docker run -it mycontainer
bash 8 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 8 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 8 root 2u CHR 136,0 0t0 3 /dev/pts/0
stdin, stdout, stderr are connected to a tty and the host stdin is connected.
Check if connected to a tty
Here are some code, I found around the internet.
if tty -s
then
echo "Terminal connected."
else
echo "No Terminal connected."
fi
This is true as long the option -t is given. I think to check if option -i was given on the docker run command is not possible.
if [ -t 0 ]; then
echo "stdin is connected to a terminal."
fi
if [ -t 1 ]; then
echo "stout is connected to a terminal."
fi
if [ -t 2 ]; then
echo "stderr is connected to a terminal."
fi
This checks everything separate.
Furthermore it is possible to check for a pipe:
if [[ -p /dev/stdin ]] ; then
echo "stdin is coming from a pipe"
fi
if [[ -t 0 ]] ; then
echo "stdin is coming from the terminal"
fi
if [[ ! -t 0 && ! -p /dev/stdin ]] ; then
echo "stdin is redirected"
fi
Interactive Shell with docker-compose
https://stackoverflow.com/a/39150040/17875203
version: "3"
services:
app:
image: app:1.2.3
stdin_open: true # docker run -i
tty: true # docker run -t