compose: docker-compose exec: the input device is not a TTY

Description of the issue

Cannot start interactive shell (e.g. /bin/bash) using docker-compose -f - exec

Context information (for bug reports)

Output of docker-compose version

docker-compose version 1.25.4, build unknown
docker-py version: 4.2.0
CPython version: 3.8.2
OpenSSL version: OpenSSL 1.1.1e  17 Mar 2020

Output of docker version

Client:
 Version:           19.03.8-ce
 API version:       1.40
 Go version:        go1.14
 Git commit:        afacb8b7f0
 Built:             Mon Mar 16 22:23:09 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.8-ce
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.14
  Git commit:       afacb8b7f0
  Built:            Mon Mar 16 22:22:53 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.3.3.m
  GitCommit:        d76c121f76a5fc8a462dc64594aea72fe18e1178.m
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Steps to reproduce the issue

  1. Run the following commands:
#!/bin/bash
read -d '' COMPOSE_FILE << EOF
version: '3'
services:
  hello:
    image: "redis:alpine"
EOF

echo "$COMPOSE_FILE"
echo "$COMPOSE_FILE" | docker-compose -f - up -d
echo "$COMPOSE_FILE" | docker-compose -f - exec hello /bin/sh

Observed result

Command quits immediately with the following message:

the input device is not a TTY

Expected result

Interactive shell starts

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 27
  • Comments: 22

Commits related to this issue

Most upvoted comments

you can try either: export COMPOSE_INTERACTIVE_NO_CLI=1 or run: docker-compose exec -T ...

see discussion: #5696

I’m experiencing this issue when running a docker-compose exec command from a crontab cronjob.

docker-compose exec -T solved the issue for me.

@jennydaman yes, it still does not work.

Everyone else commenting here that -T solves the problem, doesn’t understand what “interactive shell” means.

I’m experiencing this issue when running a docker-compose exec command from a crontab cronjob.

I really think you should invoke docker exec -it directly here. eg.: docker exec -it $(docker-compose ps -q web) /bin/bash instead, if you don’t want to give it a fixed name.

I came here looking for a totally different purpose. Wanted to add docker commands to a pre-commit hook and got the error input device is not a tty

Solved it using: docker exec --tty $(docker-compose ps -q web) /bin/bash from this link

Thanks for the dynamic container id idea. 😃

@lingster neither of those works: export COMPOSE_INTERACTIVE_NO_CLI=1 results in error:

Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/dockerpty/pty.py", line 334, in start
    self._hijack_tty(pumps)
  File "/usr/lib/python3.8/site-packages/dockerpty/pty.py", line 373, in _hijack_tty
    pump.flush()
  File "/usr/lib/python3.8/site-packages/dockerpty/io.py", line 367, in flush
    read = self.from_stream.read(n)
  File "/usr/lib/python3.8/site-packages/dockerpty/io.py", line 121, in read
    return os.read(self.fd.fileno(), n)
  File "/usr/lib/python3.8/socket.py", line 718, in fileno
    self._checkClosed()
ValueError: I/O operation on closed file.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/bin/docker-compose", line 11, in <module>
    load_entry_point('docker-compose==1.25.4', 'console_scripts', 'docker-compose')()
  File "/usr/lib/python3.8/site-packages/compose/cli/main.py", line 72, in main
    command()
  File "/usr/lib/python3.8/site-packages/compose/cli/main.py", line 128, in perform_command
    handler(command, command_options)
  File "/usr/lib/python3.8/site-packages/compose/cli/main.py", line 519, in exec_command
    pty.start()
  File "/usr/lib/python3.8/site-packages/dockerpty/pty.py", line 338, in start
    io.set_blocking(pump, flag)
  File "/usr/lib/python3.8/site-packages/dockerpty/io.py", line 32, in set_blocking
    old_flag = fcntl.fcntl(fd, fcntl.F_GETFL)
  File "/usr/lib/python3.8/site-packages/dockerpty/io.py", line 351, in fileno
    return self.from_stream.fileno()
  File "/usr/lib/python3.8/site-packages/dockerpty/io.py", line 103, in fileno
    return self.fd.fileno()
  File "/usr/lib/python3.8/socket.py", line 718, in fileno
    self._checkClosed()
ValueError: I/O operation on closed file.

-T switch just silences the error and nothing happens

I really think you should invoke docker exec -it directly here.
eg.: docker exec -it $(docker-compose ps -q web) /bin/bash instead, if you don’t want to give it a fixed name.

Just to add some practical perspective, I observed the following with a mysql:8.0 container (defined as mysql in my docker-compose.yml):

  • For an interactive mysql prompt, you have to omit the -T flag:
    docker-compose exec mysql sh -c 'exec mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"'`
    
  • When using stdin/stdout instead, you have to provide the -T flag:
    docker-compose exec -T mysql sh -c 'exec mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' < backup.sql
    # OR
    echo "SHOW TABLES" | docker-compose exec -T mysql sh -c 'exec mysql -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"'
    

Yeah the original problem is not solved; those saying that -T solves it have come here from searching “docker-compose exec input device is not a TTY”.

My guess is that echo "$COMPOSE_FILE" | docker-compose -f - exec -T hello /bin/sh silences the error but does nothing because the docker-compose process is forwarding its stdin (which is also from echo "$COMPOSE_FILE") to sh, and so sh reaches the end of its stdin and exits.

you can try either: export COMPOSE_INTERACTIVE_NO_CLI=1 or run: docker-compose exec -T ...

see discussion: #5696

@lingster . Thank you very much. It resolved for me