How to fix the input device is not a TTY in Docker

DockerBEGINNERLOWUpdated Dec 6, 2025ยท 317 views

The 'input device is not a TTY' error occurs when Docker commands include the -t flag (which requests a pseudo-terminal) but are run in a non-interactive environment like CI/CD pipelines or automated scripts. Remove the -t flag or use the -T flag with docker-compose exec.

Quick fix

Fixes the input device is not a TTY

# Instead of this (fails without TTY):
docker run -it myimage /bin/sh

# Use this (works without TTY):
docker run -i myimage /bin/sh

# Or if you don't need any interactivity:
docker run myimage /bin/sh -c "your-command"
  1. Remove the -t flag from docker run commands
  2. Use -T flag with docker-compose exec
  3. Update CI/CD pipeline commands
  4. Fix piped commands
docker โ€” error
# Instead of this (fails without TTY):
docker run -it myimage /bin/sh
# Use this (works without TTY):
docker run -i myimage /bin/sh
# Or if you don't need any interactivity:
docker run myimage /bin/sh -c "your-command"
the input device is not a TTY

What this error means

The "the input device is not a TTY" error occurs when Docker tries to allocate a pseudo-terminal (TTY) but the environment running the command doesn't have one available. A TTY (teletypewriter) is a terminal interface that allows interactive input and output between you and a program. When you use the `-t` flag with `docker run` or `docker exec`, Docker attempts to allocate a pseudo-TTY for the container. However, this requires that Docker itself is running in a TTY environment. In non-interactive environments like CI/CD pipelines (GitHub Actions, Jenkins, GitLab CI), cron jobs, or when piping commands, there is no TTY available. When Docker detects this mismatch - you're asking for a TTY but running in an environment without one - it throws this error to alert you that interactive features won't work as expected.

Typical symptoms

  • Docker run or exec commands fail with 'the input device is not a TTY' message
  • Commands work locally but fail in CI/CD pipelines like GitHub Actions or Jenkins
  • docker-compose exec fails with TTY error in automated scripts
  • Commands fail when run inside shell scripts or cron jobs
  • Piping input to Docker commands causes TTY errors
  • The same command works in an interactive terminal but fails in non-interactive contexts

Common causes

  1. Using the -t flag in a non-interactive environment (CI/CD, cron, scripts)
  2. Running docker run -it in GitHub Actions, Jenkins, or GitLab CI pipelines
  3. Using docker-compose exec without the -T flag in automated environments
  4. Piping input to a Docker command that has the -t flag (e.g., echo 'cmd' | docker run -it ...)
  5. Running Docker commands from Windows Git Bash (mintty) which doesn't provide a native TTY
  6. Executing Docker commands from IDEs or editors that don't allocate a terminal

How to fix "the input device is not a TTY"

1Remove the -t flag from docker run commands

If you don't need an interactive terminal, simply remove the -t flag from your command:

bash
# Instead of this (fails without TTY):
docker run -it myimage /bin/sh

# Use this (works without TTY):
docker run -i myimage /bin/sh

# Or if you don't need any interactivity:
docker run myimage /bin/sh -c "your-command"

The -i (interactive) flag keeps STDIN open without requiring a TTY, which is sufficient for most automated use cases.

2Use -T flag with docker-compose exec

For docker-compose exec, use the -T flag to disable pseudo-TTY allocation:

bash
# Instead of this:
docker-compose exec myservice sh -c "echo hello"

# Use this:
docker-compose exec -T myservice sh -c "echo hello"

The -T flag explicitly tells docker-compose not to allocate a TTY, making the command work in non-interactive environments.

For docker compose (V2), the same flag works:

bash
docker compose exec -T myservice sh -c "echo hello"
3Update CI/CD pipeline commands

In your CI/CD configuration files, ensure Docker commands don't use the -t flag:

GitHub Actions example:

yaml
steps:
  - name: Run tests in container
    run: |
      docker run -i myimage npm test
      docker-compose exec -T app ./run-tests.sh

Jenkins Pipeline example:

groovy
sh 'docker run -i myimage npm test'
sh 'docker-compose exec -T app ./run-tests.sh'

GitLab CI example:

yaml
test:
  script:
    - docker run -i myimage npm test
    - docker-compose exec -T app ./run-tests.sh
4Fix piped commands

When piping input to Docker, the -t flag won't work because STDIN comes from the pipe, not a terminal:

bash
# This fails:
echo "ls -la" | docker run -it alpine sh

# This works (remove -t, keep -i):
echo "ls -la" | docker run -i alpine sh

For commands that read from STDIN:

bash
# Pass file contents to container:
cat script.sh | docker run -i alpine sh

# Or use redirection:
docker run -i alpine sh < script.sh
5Fix Windows Git Bash (mintty) issues

Git Bash on Windows uses mintty, which doesn't provide a native Windows TTY. Use one of these solutions:

Option 1: Use winpty prefix:

bash
winpty docker run -it alpine sh

Option 2: Use PowerShell instead:
PowerShell provides proper TTY support on Windows.

powershell
docker run -it alpine sh

Option 3: Use Windows Terminal:
Windows Terminal with Git Bash provides better TTY compatibility.

Option 4: Configure Git Bash:
Add to your ~/.bashrc:

bash
# Automatically use winpty for docker commands
alias docker='winpty docker'
6Conditionally enable TTY based on environment

In scripts that run both interactively and in CI, detect TTY availability:

bash
#!/bin/bash
# Check if running in a TTY
if [ -t 0 ]; then
  # Interactive - use -it
  docker run -it myimage /bin/sh
else
  # Non-interactive - use -i only
  docker run -i myimage /bin/sh
fi

Or use a one-liner:

bash
docker run $([ -t 0 ] && echo "-it" || echo "-i") myimage /bin/sh

This makes your scripts work in both environments without modification.

Advanced notes

### Understanding -i vs -t Flags

The -i and -t flags serve different purposes:

- `-i` (interactive): Keeps STDIN open even if not attached. Required if you want to send input to the container.
- `-t` (tty): Allocates a pseudo-TTY. Provides terminal features like colored output, command history, and proper signal handling.

When combined as -it, you get a full interactive terminal experience. However, -t requires a real TTY on the host side.

### TTY Detection in Docker

Docker checks if its own STDIN is a TTY before allocating a pseudo-TTY:

bash
# Check if current shell has a TTY
if [ -t 0 ]; then
  echo "STDIN is a TTY"
else
  echo "STDIN is not a TTY"
fi

# Check if STDOUT is a TTY
if [ -t 1 ]; then
  echo "STDOUT is a TTY"
fi

### Common CI/CD Environment Variables

Many CI systems set environment variables you can check:

bash
# GitHub Actions
if [ "${GITHUB_ACTIONS}" = "true" ]; then
  DOCKER_FLAGS="-i"
else
  DOCKER_FLAGS="-it"
fi

# Jenkins
if [ -n "${JENKINS_HOME}" ]; then
  DOCKER_FLAGS="-i"
else
  DOCKER_FLAGS="-it"
fi

# Generic CI detection
if [ "${CI}" = "true" ]; then
  DOCKER_FLAGS="-i"
else
  DOCKER_FLAGS="-it"
fi

docker run ${DOCKER_FLAGS} myimage /bin/sh

### Makefile Considerations

In Makefiles, commands don't run in a TTY by default:

makefile
# This may fail with TTY error
shell:
	docker run -it myimage /bin/sh

# Use this instead
shell:
	docker run -i myimage /bin/sh

# Or detect TTY availability
shell:
	@if [ -t 0 ]; then \
		docker run -it myimage /bin/sh; \
	else \
		docker run -i myimage /bin/sh; \
	fi

### Why Some Commands Need TTY

Certain commands require a TTY to function properly:
- Interactive shells (bash, zsh, sh in interactive mode)
- Text editors (vim, nano)
- Programs using ncurses (htop, less with certain options)
- Commands that prompt for passwords

For these use cases in CI, consider alternatives:
- Use non-interactive modes (bash -c "command" instead of interactive bash)
- Set passwords via environment variables or config files
- Use expect scripts for automation if interaction is truly required

Frequently asked questions

What does "the input device is not a TTY" mean?
The "the input device is not a TTY" error occurs when Docker tries to allocate a pseudo-terminal (TTY) but the environment running the command doesn't have one available. A TTY (teletypewriter) is a terminal interface that allows interactive input and output between you and a program. When you use the -t flag with docker run or docker exec, Docker attempts to allocate a pseudo-TTY for the container.
How do I fix "the input device is not a TTY"?
The 'input device is not a TTY' error occurs when Docker commands include the -t flag (which requests a pseudo-terminal) but are run in a non-interactive environment like CI/CD pipelines or automated scripts. Remove the -t flag or use the -T flag with docker-compose exec.
What causes "the input device is not a TTY"?
Using the -t flag in a non-interactive environment (CI/CD, cron, scripts) Running docker run -it in GitHub Actions, Jenkins, or GitLab CI pipelines Using docker-compose exec without the -T flag in automated environments
Is the "the input device is not a TTY" error serious?
It is a low-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading