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.

Best practices
Illustration of application infrastructure and operations

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

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting