0

I have this docker-compose file:

version: "2"

services: 
    test:
        image: python:3
        stdin_open: true
        tty: true
        container_name: test_c

If I just run docker-compose up it doesn't work

$ sudo docker-compose up 
Recreating test_c
Attaching to test_c
test_c  | Python 3.8.2 (default, Feb 26 2020, 14:58:38) 
test_c  | [GCC 8.3.0] on linux
test_c  | Type "help", "copyright", "credits" or "license" for more information.
^CGracefully stopping... (press Ctrl+C again to force)
Stopping test_c ... 
Killing test_c ... done

I can work around it by doing:

$ sudo docker-compose up -d
$ sudo docker attach test_c
>>> 

But I want to know why doesn't just work with docker-compose up.

Whack
  • 133
  • 1
  • 6

2 Answers2

3

docker-compose was built as orchestration tool for long-running services. Therefor docker-compose up is not intended to be used for interactive services and does not allocate a tty or attach stdin to them by default.

To run a service interactively use docker-compose run e.g.

docker-compose run test

which will by default allocate a tty and attach to stdin of that service, so you don't need stdin_open and tty in docker-compose.yml.


If you want to run your service in the background but it requires interactive input to start up I'd suggest to rework that service if possible to be able to start non-interactively.

acran
  • 7,070
  • 1
  • 18
  • 35
2

What is happening here is that you are spawning an instance of Python and then not providing the command any arguments. Docker containers are essentially abstractions around filesystems and resources for single processes from the kernel of the Host OS.

So, in this case, the image you are calling just simply gets created and then calls Python. What happens if you call Python in your shell on your computer? It dumps you into an interactive shell that you can then submit commands to.

Well, that doesn't make much sense. Why call a command that just spins up a shell in a namespaced environment that can't communicate with anything else? The real way to use Docker would be to pass arguments to that container image. So that when Docker starts up the Python process, it can pass it an argument to do something. For example, run an application that was volume mounted in or copied in via the Dockerfile.

So how do we do that? Well, we can provide your docker-compose file with some Arguments through the Args field!

But, to me, it looks like you're just playing around here. So you likely don't have a project to pass to Python with the args field. Or to back into a new Docker Image. What you're likely trying to do is to get into the shell of Python.

The reason that this doesn't automatically happen when Docker runs the python command, is because docker-compose up or docker run doesn't drop you into an interactive environment. It just calls the entrypoint command in the container. To do that, you have to call an ADDITIONAL command in the container. In this case, a shell. Most container OS come with something like sh or bash installed on them. I DOUBT that python does. However, you can test it using the exec command like so:

docker-compose up -d
docker exec -it test_c

Let me know if you need any additional info or support for this question. Always happy to help you get started with Docker. It's an awesome technology!

TJ Zimmerman
  • 3,100
  • 25
  • 39
  • 2
    Thanks, this is a very clear and elaborate answer. My confusion was because I assumed that if I'm not detached, then I'm attached, and if I'm attached then I'm interactive. But I suppose attached just means that I see the output. – Whack Mar 31 '20 at 13:21
  • And why with other images I can't do it, I just asked here https://stackoverflow.com/questions/66638731/why-do-i-need-tty-true-in-docker-compose-yml-and-other-images-do-not – jcarlosweb Mar 15 '21 at 15:02