Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
carbolymer opened this issue Mar 21, 2020 · 23 comments
Closed

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

carbolymer opened this issue Mar 21, 2020 · 23 comments

Comments

@carbolymer
Copy link

carbolymer commented Mar 21, 2020

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

@carbolymer carbolymer changed the title the input device is not a TTY docker-compose exec: the input device is not a TTY Mar 21, 2020
@lingster
Copy link

lingster commented Mar 22, 2020

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

see discussion: #5696

@carbolymer
Copy link
Author

@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

@dobleme
Copy link

dobleme commented May 5, 2020

Experiencing the same issue!

@caugner
Copy link

caugner commented May 20, 2020

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

@abranhe
Copy link

abranhe commented May 21, 2020

I am trying to backup a database from MySQL image and I am getting the same issue.

docker-compose exec db-service mysqldump -u root -proot db > ./db.sql

@caugner
Copy link

caugner commented May 21, 2020

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.

@Azatalion
Copy link

Azatalion commented Sep 2, 2020

Got similar problem, when was trying to run laravel schedule in docker via cron.

My solution is type in host terminal: crontab -e

add this line: * * * * * cd /path/to/docker.yml && docker exec <docker-container's name> php artisan schedule:run >> log.txt 2>&1

save and look at log.txt

@mudlee
Copy link

mudlee commented Sep 18, 2020

I ran into this problem in a GCP environment in a startup script, where I didn't even see the error. -T solved my problem.

@jennydaman
Copy link

@carbolymer is your description up to date with docker-compose version 1.27.4?

I also get ValueError: I/O operation on closed file. when using COMPOSE_INTERACTIVE_NO_CLI=1 but the docker-compose exec works correctly with -T

@carbolymer
Copy link
Author

carbolymer commented Nov 18, 2020

@jennydaman yes, it still does not work.

Everyone else commenting here that -T solves the problem, doesn't understand what "interactive shell" means.

@kylrth
Copy link

kylrth commented Feb 26, 2021

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.

@alaincao
Copy link

alaincao commented Mar 2, 2021

Heylow, my 2 cents here.
I don't think what you are asking here is possible "in the Unix sense".
You cannot have a TTY/terminal device (ie. a combination of a screen(stdout) and a keyboard(stdin) ) at the same time as saying that 'stdin' (ie. the keyboard) is the output of an 'echo' command (and thus, not '/dev/stdin' anymore).
I think what you'd need to do is give a fixed name to the container with container_name: <mycontainername> in your docker-compose "file" and invoke directly docker exec -it <mycontainername> /bin/sh.
Possibly auto-generate a "unique" random 'mycontainername'

nb: I came here indeed searching for "docker-compose exec input device is not a TTY", therefore, my problem is solved, I was seaching for the "-T" parameter ;-)

@carbolymer
Copy link
Author

@alaincao Well, you're right. But you can get around this using: (echo "$COMPOSE_FILE" && cat) | docker-compose -f - exec hello /bin/sh (vide: https://stackoverflow.com/a/5852578/1608594 ) - but it does not work in this case also. My understanding is that docker-compose isn't able to determine when yaml file ends and when user input starts.

@alaincao
Copy link

alaincao commented Mar 3, 2021

Well, I don't think that even in the case of && cat, 'stdin' would be a TTY.
It would be the output of cat instead which is not a TTY device, but just the piped stdout of a program.
Also, if you do (echo "A" && echo "B") | cat, there's no EOF between the "A" and "B". This is not the same thing ; it's just a concatenation.

@alaincao
Copy link

alaincao commented Mar 3, 2021

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.

@caugner
Copy link

caugner commented May 6, 2021

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"'

@yashtodi94
Copy link

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. :)

@NguyenLamIT
Copy link

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

@ndeloof
Copy link
Contributor

ndeloof commented Jun 17, 2021

Compose v2 automatically applies -T if process is not running within a terminal
(https://github.com/docker/compose-cli/blob/main/cmd/compose/exec.go#L71)

@stale
Copy link

stale bot commented Apr 16, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 16, 2022
@stale
Copy link

stale bot commented Apr 27, 2022

This issue has been automatically closed because it had not recent activity during the stale period.

@stale stale bot closed this as completed Apr 27, 2022
@marcindulak
Copy link

👀

lakshmaji added a commit to lakshmaji/pt-rails-todo-api that referenced this issue Jun 26, 2024
lakshmaji added a commit to lakshmaji/pt-rails-todo-api that referenced this issue Jun 26, 2024
Containarize application along with database for development and testing activities.
Setup CI pipelines (Github actions) to run tests and build.
Added scripts improve developer experience.

docker/compose#7306
lakshmaji added a commit to lakshmaji/pt-rails-todo-api that referenced this issue Jun 26, 2024
Containarize application along with database for development and testing activities.
Setup CI pipelines (Github actions) to run tests and build.
Added scripts improve developer experience.

docker/compose#7306
@esnunes
Copy link

esnunes commented Aug 7, 2024

I can think of two scenarios where this error may occur:

  1. you are running it in an input device that is not a TTY.
  2. you are piping something to docker compose, therefore the input becomes non-interactive (that was the scenario I was facing when I found this issue and to solve it you just need to tell docker compose that you are not longer expecting a TTY with the -T flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests