Skip to content
DevOps AI ToolKit
Newsletter
All guides
Docker with AI By James Joyner IV · · 9 min read

Docker Error Guide: 'the input device is not a TTY' in CI and Scripts

Quick answer

Fix Docker's 'the input device is not a TTY' error from docker run/exec -it in CI or non-interactive shells: drop the -t flag and run containers cleanly in pipelines.

Part of the Docker Container & Runtime Errors hub
  • #docker
  • #troubleshooting
  • #errors
  • #cli
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Exact Error Message

the input device is not a TTY

You may also see the Windows-shell variant the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty', or the closely related input device is not a TTY and cannot enable tty mode on non tty input. All of them come from Docker’s CLI when you request a terminal that the current environment cannot provide.

What It Means

The -t (--tty) flag on docker run and docker exec tells Docker to allocate a pseudo-terminal (PTY) and attach it to the container’s process. Allocating a PTY only makes sense when the command’s input is actually connected to a real terminal. In a CI job, a cron task, a bash -c subshell, or any pipeline where stdin is a pipe or file rather than a terminal, there is no TTY to attach, so Docker refuses with the input device is not a TTY.

This is almost always caused by copy-pasting an interactive command (docker exec -it ...) into an automated, non-interactive context. The -i (keep stdin open) part is usually fine; it is the -t that fails.

Common Causes

  • Running docker run -it or docker exec -it inside a CI pipeline (GitHub Actions, GitLab CI, Jenkins) where no terminal is attached.
  • Invoking Docker from a script executed by cron, systemd, or a git hook.
  • Piping into the command, for example echo cmd | docker exec -it web sh, which redirects stdin away from a terminal.
  • Using Git Bash / MinTTY on Windows, which does not present a native Windows console to Docker.
  • Wrapping the command in $(...) command substitution, which also detaches the terminal.

Diagnostic Commands

Check whether stdin is actually a terminal in the current shell:

[ -t 0 ] && echo "stdin is a TTY" || echo "stdin is NOT a TTY"

Inspect the failing command to see whether -t is present:

tty

Reproduce the failure by forcing a non-terminal stdin:

echo hi | docker run -it --rm alpine echo test

Confirm the container works without a TTY:

docker run -i --rm alpine echo test

Step-by-Step Resolution

  1. Identify where the command runs. If it is CI, cron, a script, or a pipe, there is no terminal, so -t cannot succeed.

  2. Drop the -t flag. Keep -i only if the process needs stdin (for example piping data in); remove both if it needs neither:

# interactive (terminal) — original
docker exec -it web sh

# CI / script — allocate no TTY
docker exec -i web sh -c "app migrate"

# no stdin needed at all
docker exec web sh -c "app migrate"
  1. For docker run in a pipeline, the same rule applies:
docker run --rm -i myimage python manage.py migrate
  1. Make it work in both interactive and automated contexts by allocating a TTY only when one exists:
DOCKER_TTY=""
[ -t 0 ] && DOCKER_TTY="-t"
docker exec -i $DOCKER_TTY web sh
  1. On Windows with Git Bash / MinTTY, prefix the command with winpty to bridge to a Windows console:
winpty docker exec -it web sh
  1. Re-run the automated command and confirm it exits cleanly:
test

Prevention

  • Reserve docker run -it and docker exec -it for interactive terminals only; never bake -t into scripts or pipelines.
  • In CI configuration, standardize on docker exec -i (or no flags) so jobs are portable across runners.
  • Guard the -t flag behind a [ -t 0 ] check in shared helper scripts that run both interactively and in automation.
  • Document in your runbooks that -it is a human convenience, not a requirement, so teammates do not paste it into jobs.
  • On Windows, prefer PowerShell or a native console over MinTTY for Docker interactive sessions, or use winpty.
  • cannot enable tty mode on non tty input — an older wording of the same -t problem.
  • input device is not a TTY. If you are using mintty, try prefixing ... 'winpty' — the Windows/MinTTY-specific form.
  • Error: No such container — a different failure where the target container name is wrong.
  • unable to upgrade to tcp, received 400 — an exec transport issue, not a TTY issue.

Frequently Asked Questions

What is the difference between -i and -t? -i keeps stdin open so you can pipe or type input; -t allocates a pseudo-terminal. In automation, keep -i if you need stdin but drop -t.

Why does it work on my laptop but fail in CI? Your laptop shell has a real terminal attached to stdin, so -t succeeds. CI runners have no terminal, so allocating a PTY fails.

Can I just always use -i without -t? Yes for scripts and pipelines. -i alone streams stdin without needing a terminal, which is exactly what automated jobs want.

How do I fix this in Git Bash on Windows? Prefix the command with winpty, for example winpty docker exec -it web sh, or switch to PowerShell where Docker sees a native console. For ready-made CI-safe command patterns, use the DevOps AI prompt library.

Does removing -t change my container’s behavior? No. The container process runs the same; you simply do not get an interactive terminal attached. For scripted commands that is the correct behavior. See more Docker guides.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.