Fix Docker’s “the input device is not a TTY” error
Understand Docker’s -i and -t flags and choose the right options for CI jobs, pipelines, Compose, and interactive shells.
In a CI job or pipeline, replace docker run -it with docker run -i if the command needs piped input, or remove both flags if it does not. -i keeps standard input open; -t allocates a pseudo-terminal. They solve different problems.
When Docker attaches non-terminal standard input while requesting an interactive TTY, it can report:
the input device is not a TTY
Reproduce and understand the mismatch
A command copied from an interactive terminal may fail in Jenkins or another non-interactive runner:
# In a runner without terminal input:
docker run -it ubuntu bash
-i is independent of terminals: it is what allows a process in the container to consume piped data. With -i and -t together, Docker checks whether the attached input is a terminal.
printf 'hello\n' | docker run --rm -i ubuntu cat
# Prints hello, then exits when input closes.
docker run --rm ubuntu printf 'hello\n'
# A batch command usually needs neither flag.
Choose options for the execution environment
| Situation | Pattern |
|---|---|
| One-off CI command | docker run --rm image cmd |
| Piped input | cat data.sql \| docker run --rm -i image cmd |
| Batch command in an existing container | docker exec container cmd |
| Interactive local debugging | docker run --rm -it image shell |
Here, image, cmd, and shell are placeholders for your actual image and command.
For a Bash script used both locally and in CI, select terminal flags explicitly:
#!/usr/bin/env bash
args=()
if [ -t 0 ]; then
args=(-it)
fi
docker run --rm "${args[@]}" image cmd
This example does not forward non-terminal stdin. If the command must consume a pipe, always keep -i and add -t only for terminal input. Using a Bash array also avoids depending on unquoted word splitting, which differs across shells.
Frequently asked questions
Does Compose have equivalent options?
Use docker compose run -T or docker compose exec -T to disable TTY allocation. Defaults differ by subcommand. A service's tty: true setting controls its container terminal; it does not mean every command without a local terminal must fail.
Why does output change without -t?
Programs may disable colors and progress displays or change buffering when output is not a terminal. Some interactive programs require a terminal for more than presentation. Test the actual command and use its non-interactive mode in CI when available.
What if Docker runs through SSH?
A remote command such as ssh host "docker run -it ..." normally has no allocated terminal. Remove Docker's TTY flag for batch work, or use SSH's -tt when an interactive terminal is genuinely required.
Reference
Related reading
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan