Docker exec: the input device is not TTY
By Miro Kodet
Why Docker refused to run commands from pipeline
Recently, we encountered an issue where certain docker exec commands would not run when executed from a CI/CD pipeline (GitHub Actions in our case).
While these commands worked perfectly on our local development machines, migrating them into a script for automation led to unexpected errors. The typical command looked like this:
docker exec -it <container_name> bin/console importmap:installWhile this worked on our dev machines, the pipeline failed with the following error:
the input device is not a TTY
Why does this happen?
The culprit is the -it switch, which we often use by habit on local machines. This flag is actually a combination of two options:
-i/--interactive: Keep STDIN open even if not attached-t/--tty: Allocate a pseudo-TTY (teletypewriter)
When you run a command interactively in your terminal, Docker can allocate a TTY. However, in CI/CD pipelines, scripts, or non-interactive shells, there is no TTY device available, so Docker cannot fulfill this request and fails with the error above.
TL;DR: The Solution
Remove the -it flags when running in non-interactive environments!
Use this instead:
docker exec <container_name> bin/console importmap:installThis runs the command non-interactively, which is suitable for CI/CD pipelines and scripts.
When should you use -it?
- Use
-itwhen you want to interact with the container (e.g., open a shell, run a REPL, or debug interactively). - Omit
-itin scripts, CI/CD pipelines, or any non-interactive environment.
You can also use -i or -t separately if you only need one of the features. For example, -i is useful for commands that need STDIN but not a TTY.
What's a TTY?
TTY stands for Teletypewriter. Originally, it referred to physical devices used for textual input and output. Today, it's a software layer that emulates this behavior, allowing programs to interact with users via text.
In Docker, the -t flag allocates a pseudo-TTY, which is necessary for interactive programs. In non-interactive environments (like CI/CD), there is no TTY available, so Docker cannot allocate one, resulting in the error.
Troubleshooting Checklist
If you encounter the "the input device is not a TTY" error:
- Check your command: Are you using
-itunnecessarily? - Determine your environment: Is it interactive (local terminal) or non-interactive (script, CI/CD)?
- Try removing
-it: Most commands in automation do not need a TTY. - Consult documentation: See Docker's docs for more details on exec and TTY options.
References
By understanding the difference between interactive and non-interactive environments, and how Docker handles TTY allocation, you can avoid this common pitfall in your automation scripts and pipelines.