[Fixed] Error "The input device is not a TTY" – Docker

Photo of author
Written By M Ibrahim
boot2docker jenkins jenkins-pipeline

Quick Fix: To resolve the "The input device is not a TTY" issue, remove -it from the CLI to make it non-interactive, change it to -i for piped input, to -t for TTY support without a TTY device, or use a different command-line interface like PowerShell.

The Problem:

While running a Docker command inside a Jenkinsfile, you encounter the error message "The input device is not a TTY". Your goal is to find a solution that allows you to run a script named script.sh inside the Docker container without using interactive mode.

The Solutions:

Solution 1: Removing Interactive Mode

To resolve the error ""The input device is not a TTY"", remove the -it flag from your Docker command. This disables interactive mode and removes the need for a TTY. If you don’t require interactive mode, such as when running the command from a Jenkins or cron script, use this method.

Solution 2: Using `-i` for Input Piping

If you have input piped into the Docker command from a source other than a TTY, change the -it flag to -i. This is useful for commands like xyz | docker ... or docker ... <input.

Solution 3: Using `-t` for TTY Support

If you want TTY support but the input device doesn’t provide it, change the -it flag to -t. Use this for applications that check for a TTY to enable color formatting of the output logs or if you’ll later attach to the container with a proper terminal.

Solution 4: Using a Different Command Line Interface

If you need an interactive terminal but are not running in a terminal on Linux or macOS, use a different command line interface. PowerShell on Windows is reported to support this.

Understanding TTY

TTY (TeleTYpewriter) is a terminal interface that supports escape sequences, cursor movement, and other features. It originated from the old days of dumb terminals connected to mainframes. Today, it’s provided by Linux command terminals and SSH interfaces. (Refer to the Wikipedia article for more details.)

To observe the difference between running a container with and without a TTY, try the following:

  1. Run a container without a TTY: docker run --rm -i ubuntu bash.

  2. From within the container, install vim: apt-get update; apt-get install vim.

  3. Notice the lack of a prompt. When running vim against a file, try moving the cursor around within the file.

Solution 2: Use -T flag with docker-compose exec

To resolve the issue with the error message "The input device is not a TTY" in the context of docker-compose exec, incorporate the -T flag. The purpose of this flag is to disable the allocation of a pseudo-terminal (TTY) during the execution of the command within the container.

This proves particularly useful when working with tools or commands that may encounter issues or errors when operating in interactive mode. For instance, consider the following command:

docker-compose -f /srv/backend_bigdata/local.yml exec -T postgres backup

By including the -T flag in this command, you can execute the backup command within the postgres container without running into the "The input device is not a TTY" error. This allows you to successfully perform the backup operation without requiring interactive input or terminal-based interactions.

Additionally, you can use the -T flag in conjunction with other commands, such as mysql, as demonstrated below:

docker-compose exec -T mysql mysql -uuser_name -ppassword database_name < dir/to/db_backup.sql

Here, the -T flag ensures that the mysql command is executed in non-interactive mode, enabling you to seamlessly execute database operations like backups or queries without encountering the TTY-related error.

Solution 4: Use winpty

If you are using Git Bash on Windows, you just need to put winpty before your docker line:

winpty docker exec -it some_container bash

Solution 5: Optinally use `-t` option

In order for docker to allocate a TTY (the -t option) you already need to be in a TTY when docker run is called. Since Jenkins executes its jobs not in a TTY, you will encounter the error "The input device is not a TTY".

To fix this, you can make your script optionally use the -t option. Here’s an example:

test -t 1 &amp;&amp; USE_TTY="-t"
docker run ${USE_TTY} ...

This script will check if it is running in a TTY (by checking if file descriptor 1 is a terminal) and set the USE_TTY variable accordingly. It will then pass the USE_TTY variable to the docker run command, which will use the -t option if it is set.

This way, you can run your script both in Jenkins (without the -t option) and locally (with the -t option) without encountering the error.