moby: run -d behaviour with Python apps - "print" / stdout not working

First posted at StackOverflow but now I think this could be a bug in docker:

I have a Python (2.7) app which is started in my dockerfile:

CMD ["python","main.py"]

main.py prints some strings when it is started and goes into a loop afterwards:

print "App started"
while True:
    time.sleep(1)

As long as I start the container with the -it flag, everything works as expected:

$ docker run --name=myapp -it myappimage
> App started

And I can see the same output via logs later:

$ docker logs myapp
> App started

If I try to run the same container with the -d flag, the container seems to start normally, but I can’t see any output:

$ docker run --name=myapp -d myappimage
> b82db1120fee5f92c80000f30f6bdc84e068bafa32738ab7adb47e641b19b4d1
$ docker logs myapp
$ (empty)

But the container still seems to run;

$ docker ps
Container Status ...
myapp     up 4 minutes ... 

Attach does not display anything either:

$ docker attach --sig-proxy=false myapp
(working, no output)

I thought it could be a problem with stdout when running detached, but even printing to stderr does not work:

from __future__ import print_function
print("App started", file=sys.stderr)

does not work either.

Docker version:

Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.2
Git commit (client): a8a31ef
OS/Arch (client): linux/arm
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.2
Git commit (server): a8a31ef

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Reactions: 22
  • Comments: 15 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @jpdus.

docker attach supposed to subscribe to contents of stdout/stderr streams after you attach (in real time). It’s not supposed to show you earlier output, by design (for that you can use docker logs).

If you modify your code to:

import time

print("App started")
i = 0
while True:
    print("I'm actually alive: {0}".format(i))
    time.sleep(1)
    i += 1 

you will see:

docker attach --sig-proxy=false 45609a0b6a6db86551fc6743c52bee4d265e70977f9cf10f9c300c14d429f59a
I'm actually alive: 8
I'm actually alive: 9
I'm actually alive: 10
I'm actually alive: 11
I'm actually alive: 12
...
(exit with ctrl+c)

so it’s actually working as expected.

Another point is you want to make sure you start python with unbuffered output option:

CMD ["python", "-u", "main.py"]

otherwise it’ll take longer for any output to be flushed to stdout.

Another proof of docker attach actually works as expected is, docker run -i -t is basically docker create+run+attach. 😄

CMD python -u main.py

does in fact solve the problem, many thanks @ahmetalpbalkan !

Stumbled upon this one as I had the same issue but after some thought looks to me the right way to have timely output from a python app inside a daemonized docker container would be to use python’s logging module.

From a simple test I used to shed some light:

  • print is indeed buffered and docker logs will eventually give you that output, just after enough of it will have piled up
  • executing the same script with python -u gives instant output as said above
  • import logging + logging.warning("text") gives the expected result even without -u

Note: I used python3.5 but that should not make any difference.

interesting. can you please try with this dockerfile. I cannot reproduce it:

FROM python
COPY main.py .
CMD python -u main.py

if this doesn’t work either, can you please try adding -t parameter to docker run?